剑指 Offer 50. 第一个只出现一次的字符难度简单
在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。
示例:
s = “abaccdeff”
返回 “b”
s = “”
返回 " "
方法一 使用HashMap储存字符出现的频数
//1.使用HashMap储存字符出现的频数
//2.将字符串s转换为char型数组 toCharArray()。
//3.记录每个字符出现的频数
//关键:getOrDefault(c,0)方法,如果map中存在值为c的key,就获取c对应的value,如果不存在key:c,则返回默认值0。
//4.遍历字符串s,找到第一个出现次数为1的字符。注意是遍历字符串s。而不是遍历HashMap。
class Solution {
public char firstUniqChar(String s) {
HashMap<Character,Integer> frequency =new HashMap<Character,Integer>();
char[] chars = s.toCharArray();
for(char c:chars)
frequency.put(c,frequency.getOrDefault(c,0)+1);
for(char c:chars)
if(frequency.get(c) == 1) return c;
return ' ';
}
}
拓展:如果此题改为第一个出现的数字,则同样适用。如果没有要求找到最小的那个数,或者最小的字符(a),可以直接遍历数组,不用担心key值存放到map后无序的问题。因为每个key对应一个value,先存放的key就对应着先遍历到的下标。
方法二:使用LinkedHashMap,两次遍历实现。第一次遍历将所有字符当作key存入LinkedHashMap,map.put(c, !map.containsKey©)这一句当map中不存在c字符时,将c对应的value设为true;存在时设为false。则当遍历结束时,没有重复的字符对应的value都为true。然后我们通过get得到第一个value值为true的c字符就可了。
代码
class Solution {
public char firstUniqChar(String s) {
//为什么使用LinkedHashMap呢?因为LinkedHashMap底层实现是一个哈希表+双向链表。它可以让我们在使用get(c)方法时,得到第一个放入的c元素。
char[] chars = s.toCharArray();
for(char c:chars){
HashMap<Character,Boolean> map =new LinkedHashMap<Character,Boolean>();
// map.put(c,!containsKey(c));
map.put(c, !map.containsKey(c));//如果c字符已经出现过一次(即以及存在与hashmap中)就把它对应的value值设为false。
}
//如果s不是有序的则需要遍历LinkedHhashMap,才能保证第二遍遍历时key是有序的。
//因为字符串s即chars数组中的字符本来就是有序的,所以直接遍历s,得到的hashmap中的value就是第一个只出现一次的字符。
for(char c:chars){
if(map.get(c)) return c;
}
return ' ';
}
}