【算法】第一个只出现一次的字符

130 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第19天,点击查看活动详情

题目

在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。

解题思路

关键词:第一个出现、只出现一次、字符只包含小写字母

关键信息:只出现一次必须遍历全量、可能存在都只出现一次字符

哈希表遍历解法

哈希表遍历采用键值对方式存储每个字符,其解题思路如下:

  1. 遍历所有字符并将字符存入哈希表中。
  2. value为Boolean值依据字符是否已经存在区分,true表示字符值出现一次,false表示不只出现一次。
  3. 再次遍历字符串在哈希表中找到第一个只出现一次的字符。
    public char firstUniqChar(String s) {
         char[] chars = s.toCharArray();
         HashMap<Character,Boolean> maps = new HashMap();
         for(char value : chars){
             maps.put(value,maps.get(value) == null);
         }
         for(char value : chars){
            if(maps.get(value)) return value;
         }
         return ' ';
    }

HashMap 和LinkedHashMap的区别

上述解法为什么需要再次遍历字符串查询字符,原因在于HashMap存储是无序的,若直接遍历HashMap可能结果并不是第一个只出现一次的字符。而LinkedHashMap是基于HashMap和双向链表实现,因此可以采用LinkedHashMap来实现上述解法并通过Iterator有序遍历找到期望字符。

index查询解法

利用API方法indexOf求解。遍历字符串中每个字符然后通过indexOf方法查询该字符。当该字符满足以下两个条件说明只在字符串中出现一次:

  1. indexOf判断当前遍历下标是当前字符第一次出现的位置。
  2. indexOf判断当前字符在后面索引中不再出现。

API方法除了indexOf(String str)之外还有indexOf(String str, intstartIndex)。后面的intstartIndex表示从指定的索引处开始,返回第一次出现的指定子字符串在此字符串中的索引。

  public char firstUniqChar(String s) {
        for (int i = 0; i < s.length(); i++) {
           char value = s.charAt(i);
           //首次出现的位置是当前位置,且后面没有再出现这个字符
            if(s.indexOf(value) == i && s.indexOf(value,i+1) == -1)
                return s.charAt(i);
        }
        return ' ';
}

字母表解法

在关键信息中还有一个是字符串中字符只包含小写字母,因此解法就根据小写字母出现次数来判断结果。

  1. 可以创建一个26大小数组存放每个字符出现次数。
  2. 遍历字符串记录出现字符次数。
  3. 再次遍历字符串找到字符次数出现为1的值。
  int[] chars = new int[26]; 
  for (int i = 0; i < s.length(); i ++) chars[s.charAt(i) - 'a'] ++;
  for (int i = 0; i < s.length(); i ++) {
      if (chars[s.charAt(i) - 'a'] == 1) return s.charAt(i);
  }
  return ' ';

参考