剑指 Offer 50. 第一个只出现一次的字符

125 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情

一、题目描述

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

示例

示例1:

输入:s = "abaccdeff"
输出:'b'

示例2:

输入:s = "" 
输出:' '

限制

  • 0 <= s 的长度 <= 50000

难度:简单

此题为简单题,兄弟们可以重拳出击!

二、思路分析

众所周知,力扣上,简单题是真简单,中等题有些困难,困难题看不懂答案。

题目解析

  1. 在字符串中寻找第一个只出现一次的字符,根据题目要求,需要记录字符串中每个字符出现了几次,且要记录字符的顺序,以便能够找到第一个只出现一次的字符,如果不存在则返回空字符。
  2. 可以定义 map 容器来帮助实现题目要求
    • 遍历整个字符串,针对每个字符,使用 map 来存储每个字符对应出现的次数
    • 再次遍历字符串,按照字符串中字符的先后顺序,判断字符出现的次数,第一个出现一次的字符即结果字符;
    • 如果遍历完成后仍未找到,则返回空字符
  3. 还可以使用 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 ' ';
    }

image.png

使用容器+队列一次遍历

  • 使用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();
}

image.png

四、总结

知识点

  • 获取 map 容器中元素对应值,如果不存在返回默认值:map.getOrDefault(c,0);
  • 设置 map 容器中值,不存在设置为 1,存在则 +1:map.put(key,map.getOrDefault(c,0)+1);
  • 队列中元素入队:queue.offer();
  • 队列中元素出队:queue.poll();
  • 队列中获取队头元素:queue.peek();

最后

阳春三月,算法刷起来!LeetCode 剑指 Offer

简单题,不需要考虑太多,开干就是了。