找出数组中重复的数字。
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。示例 1:
输入:
[2, 3, 1, 0, 2, 5, 3]
输出:2 或 3
限制:
2 <= n <= 100000
这道题写出来不难,比如下面的解法:(记为方法1)
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
for i,value in enumerate(nums):
if value in nums[i+1:]: # 后面有相同的数
return value # 返回该数
return ('impossible')
但并不能通过:
改成下面的样子:(记为方法2)
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
nums_1 = []
for value in nums:
if value in nums_1:
return value
else:
nums_1.append(value)
还是超出时间限制,但看上去比之前的好一些:
继续改:(记为方法3)
class Solution:
def findRepeatNumber(self, nums: List[int]) -> int:
flags = [-1] * len(nums) # 构造长度为len(nums),所有值均为1的list
for num in nums:
if flags[num] == -1: # 开始时,flags的第num个值必为1.每遍历一个num,就将flags的第num个值变为不是1的数
flags[num] = num
else: # 某一次,flags的第num个值不是1,这说明这次的num和上一次的num是一个数,即重复了
return num # 返回重复值
这次效果就很好:
注意:上述代码中的-1必须为负数!!这样才能不和nums中的数相等。
总结:
方法1时间复杂度为:O(N^2) (for循环N,每次循环需要判断又是N);空间复杂度为O(1).
方法2的时间复杂度为:O(N^2)(for循环N,每次循环需要判断又是N);空间复杂度为O(N)(因为nums_1).
方法3的时间复杂度为:O(N)(for循环N,每次循环需要判断是1);空间复杂度为O(N)(因为flags).
可以看到,方法3的时间复杂度明显更低,因此能够通过。
这也说明了写代码不仅要能够运行,也要尽可能降低算法的复杂度。