034 · First Unique Character in a String
My First Thoughts
这道题要返回不重复的字符。既然要知道一个字符是不是“不重复”,那无论如何都得看过字符串里的字符。
第一反应是:Python 里会不会有类似 unique 或者 duplicate 的函数,可以直接判断一个字符是不是不重复?但从算法题角度看,还是要自己把这个过程写出来。
最直接的思路是先用字典计数:
def uniChar(s):
counts = {}
for char in s:
counts[char] = counts.get(char, 0) + 1
for key, value in counts.items():
if value == 1:
return key
return -1这个方向是自然的:counts 记录每个字符出现几次,后面看到哪个字符的次数是 1,就说明它是不重复字符。
比如:
s = "leetcode"
计数之后,"l" 的次数是 1,所以第一眼会觉得返回 "l" 就可以了。
Why That Is Not Enough
上面的计数思路是对的,真正需要纠正的是返回值。
题目问的是:
返回第一个不重复字符的下标。
不是返回字符本身。
所以如果 s = "leetcode",答案不是:
"l"
而是:
0
也就是说,字典 counts 负责告诉我们“这个字符出现了几次”,但最终答案还要回到原字符串 s 里,按从左到右的顺序找到第一个 counts[char] == 1 的位置。
Final Idea
关键思路是:
第一遍用字典统计每个字符出现次数;第二遍按原字符串顺序找第一个次数为
1的字符,并返回它的下标。
从原来的写法开始:
for key, value in counts.items():
if value == 1:
return key这里返回的是字符。要改成返回下标,就不要遍历 counts.items(),而是遍历原字符串:
for index, char in enumerate(s):
if counts[char] == 1:
return indexenumerate(s) 会同时给出当前位置 index 和当前字符 char。这样既能用 counts[char] 判断它是不是不重复,也能在找到答案时直接返回下标。
Why It Works
第一遍遍历结束后,counts 里保存了每个字符在整个字符串中出现的次数。
第二遍重新从左到右遍历 s。对于当前字符 char:
- 如果
counts[char] == 1,说明它在整个字符串中只出现一次 - 因为我们是从左到右遍历,所以第一个满足这个条件的字符,就是题目要的第一个不重复字符
如果第二遍走完都没有找到次数为 1 的字符,说明每个字符都重复了,返回 -1。
Code
def firstUniqChar(s):
counts = {}
for char in s:
counts[char] = counts.get(char, 0) + 1
for index, char in enumerate(s):
if counts[char] == 1:
return index
return -1Complexity
| Time | \(O(n)\) - n 是 s 的长度;第一遍计数,第二遍找第一个不重复字符 |
| Space | \(O(n)\) - 字典里最多保存 s 中出现过的不同字符 |
Takeaway
计数字典可以回答“每个字符出现了几次”,但题目如果要返回下标,最后通常还要回到原字符串里按顺序遍历。这样既保留了计数信息,也能拿到正确的位置。
← Quiz