AlgoMooc
你已开通华为OD训练营权益,还差最后一步——完成入营激活(兑换课程 + 加飞书 + 登记服务群),即可解锁全部课程与专属服务。去激活 →
← OD 20 天课程

华为 OD 训练营 · 题解精讲

LC387. 字符串中的第一个唯一字符

LC387. 字符串中的第一个唯一字符 视频地址。

题目描述

给定一个字符串 s ,找到 它的第一个不重复的字符,并返回它的索引 。如果不存在,则返回 -1 。 示例 1: 输入: s = "leetcode" 输出: 0

示例 2: 输入: s = "loveleetcode" 输出: 2

示例 3: 输入: s = "aabb" 输出: -1 提示: 1 <= s.length <= 10^5 s 只包含小写字母

题目解析

解题思路

本题要求找到字符串中第一个不重复字符的索引。核心思路是先统计每个字符的出现次数,再遍历字符串找到第一个出现次数为1的字符

用到的数据结构是哈希表(Python 的 Counter 本质是字典),用于存储字符到频率的映射。算法分为两步: 1. 一次遍历统计频率(Counter(s) 内部实现为 O(n) 的哈希表计数)。 2. 第二次遍历字符串,按原顺序检查每个字符的频率,遇到频率为1的立即返回索引。

关键步骤

1. 统计频率cnt = Counter(s),例如 s = "leetcode",得到 {'l':1, 'e':3, 't':1, 'c':1, 'o':1, 'd':1}。 2. 顺序查找:使用 enumerate(s) 同时获取索引 i 和字符 v,检查 cnt[v] == 1

  • 例如 "loveleetcode",遍历到索引2的 'v' 时频率为1,立即返回2。

3. 未找到返回 -1:若遍历结束无满足条件的字符,返回 -1。

ASCII 示意图(以 "leetcode" 为例):


索引: 0   1   2   3   4   5   6   7
字符: l   e   e   t   c   o   d   e
频率: 1   3   3   1   1   1   1   3
      ↑ 第一个频率为1的字符,返回0

复杂度分析

  • 时间复杂度:O(n),其中 n 为字符串长度。两次线性遍历(计数和查找),每次操作均为 O(1) 的哈希表访问。
  • 空间复杂度:O(1)。虽然使用了哈希表,但字符集固定为26个小写字母,因此空间为常数级。

参考代码

# 本题涉及到 Python 的一些语法知识
# Python常用内置函数、方法、技巧汇总
# https://og7kl7g6h8.feishu.cn/docx/AbbMdd4YHoGeQRxRGKJcJZs6nDb
class Solution:
    def firstUniqChar(self, s: str) -> int:
        # Counter 可以直接统计字符串、列表等可迭代对象的元素频率
        # s = "leetcode"
        # cnt = Counter({'e': 3, 'l': 1, 't': 1, 'c': 1, 'o': 1, 'd': 1})
        cnt = Counter(s)
        print(cnt)

        # 如果想在for循环中同时获得列表的索引 i 和元素值 v
        # 可以使用枚举内置函数 enumerate()
        for i, v in enumerate(s):
            # 如果找到了某个字符出现的频率为 1
            if cnt[v] == 1:
                # 返回它的下标即可
                return i

        # 如果不存在,则返回 -1 
        return -1