三種方法詳解:劍指Offer 03. 數組中重複的數字

LeetCode:劍指Offer 03. 數組中重複的數字

原題LeetCode鏈接:劍指Offer 03. 數組中重複的數字

題目:找出數組中重複的數字

​ 在一個長度爲 n 的數組 nums 裏的所有數字都在 0~n-1 的範圍內。數組中某些數字是重複的,但不知道有幾個數字重複了,也不知道每個數字重複了幾次。請找出數組中任意一個重複的數字。

示例1:

輸入:
[2, 3, 1, 0, 2, 5, 3]
輸出:2或3

限制:2 ≤ n ≤ 100000

方法一:排序

​ 思路:數組元素是數字,對其進行排序,若有重複則在排序後數組的相鄰位置,遍歷數組即可找到。排序時間複雜度O(nlogn),空間複雜度O(1)。C++代碼如下:

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        int length = nums.size();
        for(int i = 0; i < length-1; i++){
            if(nums[i] == nums[i+1]){
                return nums[i];
            }
        }
        return -1;
    }
};

tips: sort()用法:

頭文件:#include<algorithm>
void sort (RandomAccessIterator first, RandomAccessIterator last);
void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);

first:待排序數組起始位置;

last:待排序數組末尾位置,要排序的最後一個元素的後一個元素位置,[first,last);

comp:排序的方法,可以是升序也可以是降序,不寫則默認升序。

方法二:集合法、unordered_set

思路:首先構建一個空集合,然後遍歷數組,如果元素不在集合中則將其插入集合中;若元素在集合中,則說明有重複。

tips :set內部使用紅黑樹實現,具有自動排序的功能,因此內部元素在任何時候都是有序的;unordered_set基於哈希表,數據插入和查找時間複雜度低,代價是消耗較多內存,不能自動排序。本題只需要插入與查找,因此選用unordered_set 時間上的差別可自行嘗試使用兩種結構進行提交。空間複雜度O(n),時間複雜度爲O(n)。C++代碼如下:

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        unordered_set<int> s;
        int length = nums.size();
        for(int i = 0; i < length; i++){
            if(s.find(nums[i]) == s.end()){
                s.insert(nums[i]);
            }
            else{
                return nums[i];
            }
        }
        return -1;
    }
};

方法三:就地交換

思路:因爲數組中的數字都是在0~n-1範圍內的,如果沒有重複的元素那麼數據值和下標應該是相等的。而如果有重複的值的話,有些位置放的就不是對應的值,那麼我們可以嘗試將它放回對應的位置。

1)如果對應的位置有一個符合的元素,就說明該數字重複了;

2)如果對應的位置也不是符合的元素,那麼就將兩者交換,將上一個元素和正確位置配對,繼續尋找新的元素的位置。

class Solution {
public:
    int findRepeatNumber(vector<int>& nums) {
        int length = nums.size();
        for(int i = 0; i < length; i++){
            if(i == nums[i]){//如果元素和位置對應,則繼續
                continue;
            }
            else{//否則
                while(i != nums[i]){//循環,直到元素與位置對應
                    if(nums[nums[i]] == nums[i]){//此元素對應的位置上已經有一個符合的了
                        return nums[i];//說明已經重複,返回元素即可
                    }
                    else{//元素對應位置上也是不符合的元素,那麼就和此元素交換使它符合,然後繼續尋找新位置
                        int temp = nums[nums[i]];
                        nums[nums[i]] = nums[i];
                        nums[i] = temp;
                    }
                }
            }
        }
        return -1;
    }
};

如果有錯誤之處,還望指出!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章