题目描述
数组里只要任意一个数出现两次或更多就返回 true,所有数都不同则返回 false。
nums = [1, 2, 3, 1]
输出 = true (开头的 1 在末尾又出现了一次)
思路解析
最直接的笨办法:每个数都和它后面所有数比一遍。一万个数就要比约一亿次,慢在「每个数都得回头把后面全看一遍」。
为什么用哈希集合:查一个数「之前见过没」是 O(1) 的。一边扫一边把见过的数存进集合,到一个新数先查集合——查到就是重复,秒返回 true。
准备开始:集合 seen 一开始是空的。从 0 号位起,从左往右扫每个数。
i=0 · 看 1:当前是 1。先查集合——空的,没有 1。这是负例:没见过,不返回,把 1 存进集合。
i=0 · 存入 1:把 1 记进集合:seen = {1}。继续看下一个数。
i=1 · 看 2:当前是 2,集合里只有 1,没有 2。又一个没见过的,存进去。
i=1 · 存入 2:把 2 也记进集合:seen = {1, 2}。
i=2 · 看 3:当前是 3,集合里没有,存进去,集合越来越「全」。
i=2 · 存入 3:把 3 记进集合:seen = {1, 2, 3}。还剩最后一个数。
i=3 · 看 1 · 命中!:转折点:当前又是 1,先查集合——1 之前存过!说明它出现了第二次。立刻返回 true,根本不用扫完。
凡是「有没有出现过 / 重复 / 见过没」的判断,第一反应就该是哈希集合:把见过的丢进去,新元素查一下即可,比排序、比两两比对都快。
参考代码(Python)
Python
1def containsDuplicate(nums):
2 seen = set() # 哈希集合,记见过的数
3 for x in nums:
4 if x in seen: # 先查:之前见过吗?
5 return True # 见过 → 有重复
6 seen.add(x) # 没见过 → 记下自己
7 return False # 扫完都没撞上 → 全不同复杂度分析
- 时间复杂度:O(n) —— 数组只扫一遍,每次查/存集合都是 O(1)
- 空间复杂度:O(n) —— 集合最多存下 n 个不同的数
套路模板
记住这个「先查、再存」的骨架,所有「判断是否有重复 / 是否出现过」的题都能套。
Python
1seen = set()
2for x in arr:
3 if x in seen: # 先查
4 return True # 撞上重复
5 seen.add(x) # 再存自己
6return False易错点
- 错误写法:先排序再看相邻是否相等 → 正确写法:直接用哈希集合一遍扫(排序是 O(n log n),且会破坏原数组顺序;集合查重只要 O(n),更快也不动原数组)
- 错误写法:先 seen.add(x) 再判断 x in seen → 正确写法:先 if x in seen 判断,再 add(顺序反了,每个数刚存就被自己查到,会把任意输入都误判成 true)
以上文字与上方动画完全同一思路:先看动画建立直觉 → 读文字巩固 → 关掉页面自己默写一遍代码,能写出来才算真的掌握。