在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。
示例 1:
输入:s = "abaccdeff" 输出:'b'
示例 2:
输入:s = "" 输出:' '
限制:
0 <= s 的长度 <= 50000
Related Topics
- 声明一个
HashMap<Character,Integer> firstShowMap
记录各个字符第一次出现的位置 - 声明一个
HashSet<Character> moreThenOneSet
保存出现超过一次的字符 - 遍历一遍字符串完成上面两个哈希集合的赋值
- 遍历
firstShowMap
,对比moreThenOneSet
处理只有出现一次的字符 - 声明
firstSingle
保存单个的字符和firstSingleIndex
对应的出现位置 - 遍历
firstShowMap
的过程中如果找到一个新的只出现过一次的字符,两者比较firstSingleIndex
,留下位置跟靠前的那一个
代码
class Solution {
public char firstUniqChar(String s) {
HashMap<Character,Integer> firstShowMap = new HashMap<>();
HashSet<Character> moreThenOneSet = new HashSet<>();
int i = -1;
while (++i < s.length()){
if (!firstShowMap.containsKey(s.charAt(i))){
firstShowMap.put(s.charAt(i),i);
}else{
moreThenOneSet.add(s.charAt(i));
}
}
final char[] firstSingle = {' '};
final int[] firstSingleIndex = {s.length()};
firstShowMap.forEach((theChar,theIndex)->{
if (!moreThenOneSet.contains(theChar)){
if (theIndex < firstSingleIndex[0]){
firstSingleIndex[0] = theIndex;
firstSingle[0] = theChar;
}
}
});
return firstSingle[0];
}
}
思路就是这样,实现形式有很多种
比如
firstSingleIndex
也可以不存下来,直接回firstShowMap
中取到- 又或者官方题解中说的那样的
moreThenOneSet
可以省略,有重复的直接修改firstShowMap
对应的value
为一个不合理的值,后面判断的时候也就根据这个不合理的值来判断。
21年11月30日,重新做了一次这个题目
class Solution {
public char firstUniqChar(String s) {
if (s.length()==0){
return ' ';
}
//重复的
boolean[] map1 = new boolean[26];
//第一次出现的位置
int[] map2 = new int[26];
Arrays.fill(map2,-1);
int idx = -1;
while (++idx < s.length()){
int charIdx = s.charAt(idx)-'a';
if (!map1[charIdx]){
if (map2[charIdx] != -1){
map1[charIdx] = true;
map2[charIdx] = -1;
}else{
map2[charIdx] = idx;
}
}
}
char ans = ' ';
int min = s.length();
for (int i = 0; i < map2.length; i++) {
if (map2[i] != -1 && map2[i] < min){
min = map2[i];
ans = s.charAt(min);
}
}
return ans;
}
}
再次思考,也可以不用两个map,在一个map上定义更多的状态来实现,除了现有的-1
表示默认没处理的情况,也可以再定一个-2
为已经有多个相同字符出现的情况
发表评论