劍指Offer典型題整理 - 爭取做最好的題解
劍指Offer03-數組中重複的數字
整理時間:2020年02月18日
題目描述
在一個長度爲 n 的數組 nums 裏的所有數字都在 0~n-1 的範圍內。數組中某些數字是重複的,但不知道有幾個數字重複了,也不知道每個數字重複了幾次。請找出數組中任意一個重複的數字。
示例
輸入:
[2, 3, 1, 0, 2, 5, 3]
輸出:2 或 3
限制:
2 <= n <= 100000
題解
這道題做起來,但是作爲一個面試題,他有很多可以深挖的知識點:
- 你是否會和面試官討論時間複雜度以及空間複雜度的要求?
- 如果要求空間複雜度爲O(1)應該怎麼做呢?
😊 解法1:hash
由於n個數字均在[0, n-1],而且n的最大值爲100000,因此可以申請一個大小爲100001的數組並全部初始化爲0,逐個將nums中的數字添加到對應的位置,如果在某個位置的計數值大於1直接返回即可。這個方法的缺點是比較佔空間,空間複雜度O(n)。
python版本
class Solution(object):
def findRepeatNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
dp = [0 for i in range(len(nums))]
for num in nums:
if dp[num] == 1:
return num
dp[num] += 1
return -1
😐 解法2:排序後從前往後查找是否存在重複
時間複雜度O(nlogn),空間複雜度O(1)
python版本
class Solution(object):
def findRepeatNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
nums.sort()
for i in range(1,len(nums)):
if nums[i]==nums[i-1]:
return nums[i]
😮 解法3:桶排序+抽屜原理
桌上有十個蘋果,要把這十個蘋果放到九個抽屜裏,無論怎樣放,我們會發現至少會有一個抽屜裏面放不少於兩個蘋果。這一現象就是我們所說的“抽屜原理”。
這個方法是解法1
的進一步優化,解法1申請了一個等大的空間用於存儲hash,那麼能不能在nums數組的基礎上直接進行映射?可以通過將數組中的每一個數字映射到對應的數組下標下面實現!這裏利用到了抽屜原理:一個數組下標只能對應一個數字,如果對應兩個及以上數字則說明當前下標對應的數字重複了。
使用抽屜原理和桶排序的思想,可以在O(1)的空間複雜度內完成這道題目。
圖解:
python版本
class Solution(object):
def findRepeatNumber(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
for i in range(len(nums)):
while nums[i] != i:
if nums[i] == nums[nums[i]]:
return nums[i]
nums[nums[i]], nums[i] = nums[i], nums[nums[i]]
return -1
C++版本
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
for (int i = 0; i < nums.size(); i++) {
while (nums[i] != i) {
if (nums[i] == nums[nums[i]]) {
return nums[i];
}
int temp = nums[nums[i]];
nums[nums[i]] = nums[i];
nums[i] = temp;
}
}
return -1;
}
};
(完)