Java 使用LinkedHashMap的字符串中的第一个唯一字符

Java 使用LinkedHashMap的字符串中的第一个唯一字符,java,string,character,linkedhashmap,Java,String,Character,Linkedhashmap,给定一个字符串,找到其中的第一个非重复字符并返回其索引。如果不存在,则返回-1 示例: s = "leetcode" return 0. s = "loveleetcode" return 2. 在我的解决方案中,我可以找到角色本身,但我希望得到角色的索引!如何更改代码以使用LinkedHashMap获取索引?提前谢谢你 publicstaticvoidfirstnonrepeatingstring(stringstr){ LinkedHashMap

给定一个字符串,找到其中的第一个非重复字符并返回其索引。如果不存在,则返回
-1

示例:

s = "leetcode"
return 0.

s = "loveleetcode"
return 2.
在我的解决方案中,我可以找到角色本身,但我希望得到角色的索引!如何更改代码以使用
LinkedHashMap
获取索引?提前谢谢你

publicstaticvoidfirstnonrepeatingstring(stringstr){
LinkedHashMap lhm=新LinkedHashMap();
char[]charArray=str.toCharArray();
for(字符:charArray){
if(lhm.get(字符)==null){
lhm.put(字符,1);
}否则{
lhm.put(字符,lhm.get(字符)+1);
}
}
对于(Map.Entry:lhm.entrySet())
if(entry.getValue()==1){
System.out.print(entry.getKey());
打破
}
}
firstNonRepeatingString(“aaabcccddeggf”);
这将打印
b
,但我想打印
3

HashSet
该集合仅用于避免再次计算已看到的字符。集合不需要遵循插入顺序,因为它的目标只是检查元素是否存在。为此,
HashSet
是一个合适的选项

StringUtils
有一些很好的util实际上,其中之一是计算源字符串中单个字符/字符串的出现次数

由于需要唯一的第一个字符,如果
集中不存在该元素,并且
countMatches
返回1,则得到了结果

如果未找到唯一性,则返回
-1
(例如),表示在字符串中未找到唯一性

public static int firstNonRepeatingCharIndex(String str) 
{
   HashSet<Character> dupSet = new HashSet<>();   //duplicates list
   for(char c : str.toCharArray()) 
   {
      if (dupSet.contains(c))
          continue;
      if (StringUtils.countMatches(str, c) == 1)
          return str.indexOf(c);
      dupSet.add(c);
   }
   return -1;
}

LinkedHashMap
只有在需要完整的地图时,才能获取统计信息或其他信息

注意:不需要添加/修改条目。如果关键点不在地图中,我们直接设置出现的次数

public static int firstNonRepeatingCharIndex(String str) 
{
  LinkedHashMap <Character , Integer> lhm = new LinkedHashMap<>();
  int c = 0, index = -1;
  for(char character : str.toCharArray()) 
  {
     if (lhm.get(character) == null)
     {
        int oc = StringUtils.countMatches(str,character);
        if (oc==1 && index<0)
           index = c;           //will only bet set once
        lhm.put(character, oc);
      }            
      if (index<0)     
        c++;                   //no need for this after index is found
   } 
   //showStatsOfMap(lhm); ?
   return index;
}
public static int firstNonRepeatingCharIndex(String str)
{
LinkedHashMap lhm=新LinkedHashMap();
int c=0,index=-1;
for(字符:str.toCharArray())
{
if(lhm.get(字符)==null)
{
int oc=StringUtils.countMatches(str,字符);
如果(oc==1&&index
HashSet
该集合仅用于避免再次计算已看到的字符。该集合不需要遵守插入顺序,因为其目标只是检查元素是否存在。因此,
HashSet
是一个合适的选项

StringUtils
有一些很好的util实际上,其中之一是计算源字符串中单个字符/字符串的出现次数

由于需要唯一的第一个字符,如果
集中不存在该元素,并且
countMatches
返回1,则得到了结果

如果未找到唯一性,则返回
-1
(例如),表示在字符串中未找到唯一性

public static int firstNonRepeatingCharIndex(String str) 
{
   HashSet<Character> dupSet = new HashSet<>();   //duplicates list
   for(char c : str.toCharArray()) 
   {
      if (dupSet.contains(c))
          continue;
      if (StringUtils.countMatches(str, c) == 1)
          return str.indexOf(c);
      dupSet.add(c);
   }
   return -1;
}

LinkedHashMap
只有在需要完整的地图时,才能获取统计信息或其他信息

注意,不需要添加/修改条目。如果键不在映射中,我们直接设置出现的次数

public static int firstNonRepeatingCharIndex(String str) 
{
  LinkedHashMap <Character , Integer> lhm = new LinkedHashMap<>();
  int c = 0, index = -1;
  for(char character : str.toCharArray()) 
  {
     if (lhm.get(character) == null)
     {
        int oc = StringUtils.countMatches(str,character);
        if (oc==1 && index<0)
           index = c;           //will only bet set once
        lhm.put(character, oc);
      }            
      if (index<0)     
        c++;                   //no need for this after index is found
   } 
   //showStatsOfMap(lhm); ?
   return index;
}
public static int firstNonRepeatingCharIndex(String str)
{
LinkedHashMap lhm=新LinkedHashMap();
int c=0,index=-1;
for(字符:str.toCharArray())
{
if(lhm.get(字符)==null)
{
int oc=StringUtils.countMatches(str,字符);

如果(oc==1&&index您有两个明显的选项,这就保留了使用
LinkedHashMap
的精神:

  • 您当前将字母映射到它出现的次数。但这实际上并不重要;您需要知道的只是字母是否唯一(您不需要计数,您只需要“如果我有计数,它会是1吗?”,这是相当少的信息),并且您需要知道它发生的位置
  • 那么,为什么不将角色映射到位置而不是计数呢?然后,如果你再次命中同一个角色,你需要在映射中放置一些东西,以确保你知道这是不好的(您不能删除它,因为第三次出现会再次添加它,这意味着您为输入
    aaabc
    给出了错误的答案。可能将其设置为-1或其他值,这意味着:这不是您想要的答案)

  • 继续编写代码,但只需在字符串中再循环一次,然后找到索引。或者只需使用字符串的
    indexOf
    方法即可。这样可以将字母“b”转换为字符串中第一个“b”出现的位置

  • 您有两个比较明显的选项,它们保留了使用
    LinkedHashMap
    的精神:

  • 您当前将字母映射到它出现的次数。但这实际上并不重要;您需要知道的只是字母是否唯一(您不需要计数,您只需要“如果我有计数,它会是1吗?”,这是相当少的信息),并且您需要知道它发生的位置
  • 那么,为什么不将角色映射到位置而不是计数呢?然后,如果你再次命中同一个角色,你需要在映射中放置一些东西,以确保你知道这是不好的(您不能删除它,因为第三次出现会再次添加它,这意味着您为输入
    aaabc
    给出了错误的答案。可能将其设置为-1或其他值,这意味着:这不是您想要的答案)

  • 继续编写代码,但只需在字符串中再循环一次,然后找到索引。或者只需使用字符串的
    indexOf
    方法即可。这样可以将字母“b”转换为字符串中第一个“b”出现的位置

  • 我的解决方案使用记录映射…需要Java14或更高版本,并启用预览功能。似乎有点冗长
    v=CharacterCount[character=v, index=2, count=1]
    
    import java.util.Comparator;
    import java.util.LinkedHashMap;
    import java.util.Map;
    import java.util.Map.Entry;
    
    public class FirstUniqueCharacterDemo {
        
        public static void main (String[] args) {
    //      String input1 = "leetcode"; // return 0
            String input1 = "loveleetcode"; // return 2
    
            Map<Character, CharacterCount> charMap = new LinkedHashMap<>();
            
            for (int i = 0; i < input1.length(); i++) {
                
                char c = input1.charAt(i);
    
                CharacterCount current = new CharacterCount(c, i, 1); // records are immutable
                CharacterCount previous = charMap.put(c, current);
                if(previous != null) {
                    current = current.merge(previous); // combine records (add 1 to count and keep lower index)
                    charMap.replace(c, current);
                }
            }
    
            Entry<Character, CharacterCount> lowestIndex = charMap.entrySet().stream()
                .filter(recordsWithOneEntry -> recordsWithOneEntry.getValue().count() == 1)
                .min(Map.Entry.comparingByValue(Comparator.comparingInt(CharacterCount::index))).orElse(null); // This will return either the CharacterCount record or null if none are found with a count of 1.
            
            System.out.println(lowestIndex);
            
        }
    
        public static record CharacterCount(char character, int index, int count) {
            public boolean isIndexGreater(int index) {
                return this.index > index;
            }
            
            public CharacterCount merge(CharacterCount cc) {
                int index = (isIndexGreater(cc.index()) ? cc.index : this.index);
                int count = this.count() > cc.count ? this.count() + 1 : cc.count() + 1;
                char c = this.character();
                return new CharacterCount(c, index, count);
            }
        }
    }
    
    public int firstNonRepeatingChar( String s ) {
      List<Integer> uniques = IntStream.range( 0, s.length() ).boxed().collect(
        partitioningBy(i -> s.indexOf(s.charAt( i ),
          s.indexOf(s.charAt( i )) + 1) == -1)).get( true );  // [3, 9, 12]
      return( uniques.isEmpty() ? -1 : uniques.get( 0 ) );    // 3
    }
    
    public int firstNonRepeatingChar( String s ) {
      return( IntStream.range( 0, s.length() ).dropWhile( i -> s.indexOf(s.charAt( i ),
        s.indexOf(s.charAt( i )) + 1) > -1).limit( 1 ).findFirst().orElse( -1 ) );  // 3
    }