剑指offer46_字符串中第一个只出现一次的字符

字符串中第一个只出现一次的字符


字符串中找出第一个只出现一次的字符。

如输入"abaccdeff",则输出b

如果字符串中不存在只出现一次的字符,返回 # 字符。

数据范围

输入字符串长度 [ 0 , 1000 ] [0,1000] [0,1000]

样例
输入:"abaccdeff"

输出:'b'

算法思路(哈希表计数)
  1. 核心思想
    • 使用哈希表统计每个字符的出现次数。
    • 二次遍历字符串,找到第一个计数为 1 的字符。
  2. 关键步骤
    • 第一次遍历:记录字符频率(unordered_map)。
    • 第二次遍历:按字符串顺序检查哈希表,返回第一个频率为 1 的字符。
    • 默认值:若无满足条件的字符,返回 '#'(或其他标记符)。
维度 说明 公式
时间复杂度 两次线性遍历字符串,哈希表操作均为 O ( 1 ) O(1) O(1) O ( n ) O(n) O(n)
空间复杂度 哈希表存储所有不同字符(最坏情况存储整个字符集,如 Unicode)。 O ( S ) O(S) O(S) S为字符集的大小

class Solution {
public:
    char firstNotRepeatingChar(string s) {
        unordered_map<char, int> h;  // 字符频率哈希表
        for (auto x : s) h[x]++;     // 第一次遍历:统计频率
        
        char res = '#';              // 默认值(无解时返回)
        for (auto x : s) {           // 第二次遍历:按顺序检查
            if (h[x] == 1) {         // 找到第一个频率为1的字符
                res = x;
                break;
            }
        }
        return res;
    }
};
示例演示

输入:"abaccdeff"

步骤:

  1. 哈希表统计:{'a':2, 'b':1, 'c':2, 'd':1, 'e':1, 'f':2}
  2. 按顺序检查:
    • 'a' → 频率为2(跳过)
    • 'b' → 频率为1(返回 'b'
      输出:'b'

**变种与优化 **
  1. 空间优化

    • 若字符集为 ASCII(256个字符),可用固定数组代替哈希表:

      int count[256] = {0};  // 初始化为0
      

      空间复杂度降至 O ( 1 ) O(1) O(1)(固定大小数组)。

  2. 单次遍历实现

    • 使用哈希表同时记录字符首次出现的位置和频率,最后扫描哈希表找最小位置。
    • 时间复杂度仍为 O ( n ) O(n) O(n),但需额外空间存储位置信息。
  3. 扩展问题

    • 返回所有只出现一次的字符。
    • 处理流数据(无法二次遍历时需用队列+哈希表)。

你可能感兴趣的:(剑指offer46_字符串中第一个只出现一次的字符)