Day1数组中的重复数字
剑指offer03. 在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
示例:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
限制:
2 <= n <= 100000
方法一:哈希表 / set
算法流程:
- 遍历数组,将不在hashTable里的数字添加到里面去。
- 如果数字在hashTable里则返回该数字。
时间复杂度:O(N),遍历数组O(N) , 添加查找均是O(1)
空间复杂度: O(N) , hashTable占用了大小O(N)的额外空间
代码实现(python)
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
hashTable = set()
for num in nums:
if(num in hashTable):
return num
hashTable.add(num)
💬set(集合) 和 dict(字典)类似 , 是一组key的集合,但是不存储value,且里面的key是唯一的。
添加元素 add(key)
删除元素 remove(key)
方法二:原地交换
数组的长度为n , 里面的整数在0~n-1的范围内,并且有元素重复,也就是说重复数字和索引是一对多的关系,我们可以遍历数组,使索引和元素的值一一对应,从而起到和字典一样的作用。
算法流程:
- 从索引 i = 0 开始,如果 nums[i] != i ,将nums[i] 与nums[nums[i]]交换位置。
- 当nums[i] = i 时 , i + 1
- 如果 nums[i] == nums[nums[i]] ,说明在’字典‘中有这个数,即重复数字,返回该数字
时间复杂度:O(N) ,遍历数组O(N),交换和查找均为O(1)
空间复杂度:O(1) , 使用常数复杂度的额外空间
代码实现:
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
i = 0
while i < len(nums):
if nums[i] == nums[nums[i]]:return nums[i]
if nums[i] == i:
i += 1 #注意python没有i++
continue
nums[nums[i]],nums[i] = nums[i],nums[nums[i]]
❗ nums[nums[i]],nums[i] = nums[i],nums[nums[i]]
这里的交换要注意python的内存机制,它是先开辟新的空间——一个集合来存放括号右边的两个数,再从左到右赋值到左边,不能写成 nums[i],nums[nums[i]] = nums[nums[i]],num[i]
,否则 nums[i]
先变化,那么 nums[nums[i]]
里的索引就变了。
由于刚开始刷题不久,写题解是为了理解得更深刻一些,并且记录一下自己犯的错误
本篇参考了leetcode上@Krahets大佬的题解。