找出數組中重複的數字。
在一個長度爲 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的時間複雜度明顯更低,因此能夠通過。
這也說明了寫代碼不僅要能夠運行,也要儘可能降低算法的複雜度。