题目描述
在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。
解析
解法一
- 遍历字符串,用HashMap<k,v>存储<字符,字符出现的次数对>,再遍历哈希表,当当前键的值为1时,返回当前键。(第一次用的是HahsMap,提交代码后执行错误,本地debug才发现put到哈希表时,顺序发生了变化,因此用LinkedHashMap代替HahsMap)
- 代码
public char firstUniqChar(String s) {
if(s.length()==0) return 32;
LinkedHashMap<Character,Integer> hash = new LinkedHashMap<>();
for(int i=0;i<s.length();i++) {
if(hash.containsKey(s.charAt(i))) {
hash.put(s.charAt(i), hash.get(s.charAt(i))+1);
}else hash.put(s.charAt(i), 1);
}
for(char key:hash.keySet()) {
int value = hash.get(key);
if(value==1) return key;
}
return 32;
}
- 运行结果:
题解中利用有序哈希表的想法写的代码如下:与我的区别主要有二:遍历字符串s的方式用的是s.toCharArray();map存储的键值对的意义不同(见解法二解释)
public char firstUniqChar(String s) {
Map<Character, Boolean> dic = new LinkedHashMap<>();
char[] sc = s.toCharArray();
for(char c : sc)
dic.put(c, !dic.containsKey(c));
for(Map.Entry<Character, Boolean> d : dic.entrySet()){
if(d.getValue()) return d.getKey();
}
return ' ';
}
运行结果是:42%/55%
解法二
题解中用<k,v>存储<字符,boolean>,其中boolean表示:在插入当前字符时不存在此key则为true,存在此key为false,从而遍历哈希表时得到值为true的键。(此处作者用遍历sc保证了字符的顺序,所以不必用LinkedHashMap代替HashMap)
public char firstUniqChar(String s) {
HashMap<Character, Boolean> dic = new HashMap<>();
char[] sc = s.toCharArray();
for(char c : sc)
dic.put(c, !dic.containsKey(c));
for(char c : sc)
if(dic.get(c)) return c;
return ' ';
}
运行结果是:54%/58%
解法三
用数组代替哈希表,以字符的ASCII码为数组下标,对应存字符出现的次数。
public char firstUniqChar(String s) {
int[] count = new int[256]; //这里的数组元素被初始化为0
char[] chars = s.toCharArray();
for(char c : chars)
count[c]++;
for(char c : chars){
if(count[c] == 1)
return c;
}
return ' ';
}