Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情。
一、题目描述
在字符串 s 中找出第一个只出现一次的字符。如果没有,返回一个单空格。 s 只包含小写字母。
示例
示例1:
输入:s = "abaccdeff"
输出:'b'
示例2:
输入:s = ""
输出:' '
限制
- 0 <= s 的长度 <= 50000
难度:简单
此题为简单题,兄弟们可以重拳出击!
二、思路分析
众所周知,力扣上,简单题是真简单,中等题有些困难,困难题看不懂答案。
题目解析
- 在字符串中寻找第一个只出现一次的字符,根据题目要求,需要记录字符串中每个字符出现了几次,且要记录字符的顺序,以便能够找到第一个只出现一次的字符,如果不存在则返回空字符。
- 可以定义 map 容器来帮助实现题目要求
- 遍历整个字符串,针对每个字符,使用 map 来存储每个字符对应出现的次数
- 再次遍历字符串,按照字符串中字符的先后顺序,判断字符出现的次数,第一个出现一次的字符即结果字符;
- 如果遍历完成后仍未找到,则返回空字符
- 还可以使用 map + queue 实现寻找第一个只出现一次的字符
- 在 2. 中使用 map 存储出现次数,使用字符串本身顺序来找第一个字符,因此需要遍历两次
- 而使用队列可以帮助省去一次遍历,即在遍历字符串的过程中,进行如下操作
- 如果字符还没有出现过,就加入队列;
- 如果字符出现过,则在容器中出现次数 +1,并且循环判断队列对头元素是否出现多次,如出现多次则出队
- 由于队列可以保证字符串放入的顺序,又将所有重复出现的字符进行出队,最终队头元素就是第一个只出现一次的字符
三、AC 代码
两次遍历+容器存储判断
- 简单方法,遍历两次,第一次存储所有出现的字符和次数,第二次判断如果出现一次则返回
public char firstUniqChar(String s) {
Map<Character,Integer> map = new HashMap<>();
for(int i = 0; i < s.length(); i++){
char c = s.charAt(i);
map.put(c,map.getOrDefault(c,0)+1);
}
for(int i = 0; i < s.length(); i++){
if(map.get(s.charAt(i)) == 1) return s.charAt(i);
}
return ' ';
}
使用容器+队列一次遍历
- 使用map和队列,一次循环即可判断
public char firstUniqChar(String s) {
Map<Character,Integer> map = new HashMap<>();
Queue<Character> queue = new LinkedList<Character>();
for(int i = 0; i < s.length(); i++){
char c = s.charAt(i);
if(map.containsKey(c)){
map.put(c,map.get(c)+1);
while(!queue.isEmpty() && map.get(queue.peek()) > 1){
queue.poll();
}
}else{
queue.offer(c);
map.put(c,1);
}
}
if(queue.isEmpty()) return ' ';
else return queue.peek();
}
四、总结
知识点
- 获取 map 容器中元素对应值,如果不存在返回默认值:
map.getOrDefault(c,0); - 设置 map 容器中值,不存在设置为 1,存在则 +1:
map.put(key,map.getOrDefault(c,0)+1); - 队列中元素入队:
queue.offer(); - 队列中元素出队:
queue.poll(); - 队列中获取队头元素:
queue.peek();
最后
阳春三月,算法刷起来!LeetCode 剑指 Offer。
简单题,不需要考虑太多,开干就是了。