Leetcode 鏈接:https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/
題目描述:
找出數組中重複的數字。
在一個長度爲 n 的數組 nums 裏的所有數字都在 0~n-1 的範圍內。數組中某些數字是重複的,但不知道有幾個數字重複了,也不知道每個數字重複了幾次。請找出數組中任意一個重複的數字。
示例 1:
輸入:
[2, 3, 1, 0, 2, 5, 3]
輸出:2 或 3
限制:
2 <= n <= 100000
解題思路:
本題解給出一個時間複雜度爲 ,空間複雜度爲 的算法。
思路很簡單,由於題目給出限制所有數字範圍是0~n-1,所以我們可以嘗試將數字i放到數組nums[i]上,這樣替換下去,當有重複的元素,我們總會碰到nums[i]==i的情況,即可判斷,但是我第二遍的code寫的有一絲醜陋,下面貼出兩版本,其中第二版參見YXC大佬的Code,不得不說NOI金牌實力就是強!
下面的算法的主要思想是把每個數放到對應的位置上,即讓 nums[i] = i。
從前往後遍歷數組中的所有數,假設當前遍歷到的數是 nums[i]=xnums[i]=x,那麼:
如果x != i && nums[x] == x,則說明 xx 出現了多次,直接返回 xx 即可;
如果nums[x] != x,那我們就把 xx 交換到正確的位置上,即 swap(nums[x], nums[i]),交換完之後如果nums[i] != i,則重複進行該操作。由於每次交換都會將一個數放在正確的位置上,所以swap操作最多會進行 nn 次,不會發生死循環。
循環結束後,如果沒有找到任何重複的數,則返回-1。
Code 1:
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int i = 0, n = nums.size();
while (nums[i]==i) i++;
if (i>=n) return -1;
while (i!=nums[i])
{
if (nums[nums[i]]==nums[i]) return nums[i];
int tmp = nums[nums[i]];
nums[nums[i]] = nums[i];
i = tmp;
}
return -1;
}
};
Code 2:
class Solution {
public:
int findRepeatNumber(vector<int>& nums) {
int n = nums.size();
if (n==0) return -1;
for (int i=0; i<n; i++)
{
if (i==nums[i]) continue;
if (i!=nums[i] && nums[nums[i]]!=nums[i]) swap(nums[i], nums[nums[i]]);
else if (nums[nums[i]]==nums[i]) return nums[i];
}
return -1;
}
};
Code 2 效果好的原因,可能是swap速度比自己寫要快一些?
最後想說;
我的源碼都整理在了github上,劍指offer專題會分類整理(如樹專題,DP專題,模擬專題,搜索專題等),github鏈接見下文,如果對您有幫助,請幫忙在github中star,這對我很重要!!!! 拜託拜託~!!