Leetcode-劍指offer-3-數組中重複的數字

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

解題思路:

本題解給出一個時間複雜度爲O(n) ,空間複雜度爲O(1) 的算法。

思路很簡單,由於題目給出限制所有數字範圍是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,這對我很重要!!!! 拜託拜託~!!

github鏈接: https://github.com/wjlpku/Leetcode-interview
 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章