找出數組中重複的數字。python
在一個長度爲 n 的數組 nums 裏的全部數字都在 0~n-1 的範圍內。數組中某些數字是重複的,但不知道有幾個數字重複了,也不知道每一個數字重複了幾回。請找出數組中任意一個重複的數字。
示例 1:算法
輸入: [2, 3, 1, 0, 2, 5, 3] 輸出:2 或 3
該題目的難度級別爲Easy。數組
最直觀的方式可能就是排序+遍歷的方式, 根據這個思路能夠很容易的寫出代碼數據結構
def findRepeatNumber(nums: List[int]) -> int: if nums == None or len(nums) < 2: return nums.sort() for i in range(1, len(nums)): # 只要找到就能夠返回 if nums[i] == nums[i-1]: return nums[i]
排序的時間複雜度爲$O(nlogn)$,遍歷的時間複雜度爲$O(n)$,即算法的時間複雜度爲$O(nlogn)$,空間複雜度爲$O(1)$。數據結構和算法
使用字典做爲計數器,只要某個元素的已經存在於字典中就能夠直接返回。按照這個思路能夠寫出以下代碼學習
def findRepeatNumber(nums: List[int]) -> int: if nums == None or len(nums) < 2: return dicts = {} for i in nums: # 只要找到就能夠返回 if i in dicts: return i dicts[i] = 1
相比於第一種算法,該算法以空間換時間。由於只有一次循環,時間複雜度爲$O(n)$,空間複雜度爲$O(n)$。優化
上面2中思路都是比較容易想到的,那麼有沒有不使用額外空間,而且時間複雜度爲$O(n)$的算法呢。spa
每次換一種思路時,咱們須要從新去思考題目,而不是在已有的思路上糾結。
若是數組nums沒有重複,那麼nums的索引所構成的集合和nums中的元素構成的集合是相等的(從集合的角度上來看,不考慮順序)。即對於任意一個索引,都有惟一的元素與它相等,相對應。3d
但若是nums包含重複元素,那麼對於部分索引,將會對應多個相同元素,好比nums = [2, 3, 1, 0, 2, 5, 3]code
索引爲2的對應數組中的2個2,索引爲3的對應數組中的2個3。咱們能夠依次的將每一個元素放到它對應的索引位置,而若是該元素和它對應索引位置的元素相等,說明該元素重複。
按照這個思路, 能夠寫出以下的代碼
def findRepeatNumber(nums: List[int]) -> int: if nums == None or len(nums) < 2: return for i in range(len(nums)): # 索引和對應元素不一致,調整元素位置,直至索引與元素匹配或者找到重複元素 while i != nums[i]: # 若是當前元素對應的索引位置的值與當前元素相等 if nums[i] == nums[nums[i]]: return nums[i] # 交換nums[i]和i位置的值 temp = nums[i] nums[i], nums[temp] = nums[temp], nums[i]
上述代碼雖然包含了2次循環,但每一個位置均可以在有限次內結束。所以總的時間複雜度爲$O(n)$,並不須要使用額外的空間,空間複雜度爲$O(1)$。
經歷了慘痛的教訓,終於決定要開始認真刷題了。以前一直是處於間歇期放棄的狀態,致使如今基本上是從零開始了。我會盡量把本身作過的題目進行一些總結,因爲本人對於數據結構和算法的學習有限,大佬勿噴。