1. 程式人生 > >劍指offer演算法題(二)陣列中重複的數字

劍指offer演算法題(二)陣列中重複的數字

劍指offer演算法題2

陣列中重複的數字

題目描述

在一個長度為n的數組裡的所有數字都在0到n-1的範圍內。 陣列中某些數字是重複的,但不知道有幾個數字是重複的。也不知道每個數字重複幾次。請找出陣列中任意一個重複的數字。 例如,如果輸入長度為7的陣列{2,3,1,0,2,5,3},那麼對應的輸出是第一個重複的數字2。

解題思路1:

由於所有數字都在 0~n-1 之間,因此,當一個數字被訪問過後,可以設定對應位上的數 + n,之後再遇到相同的數時,會發現對應位上的數已經大於等於n了,那麼直接返回這個數即可。

程式碼實現:

class Solution {
public:
    bool
duplicate(int numbers[], int length, int* duplication) { for(int i=0;i<length;i++){ int j=numbers[i]%length; numbers[j]+=length; if(numbers[j]>=(2*length)){ *duplication = numbers[j]%length; return true
; } } return false; } };

優點:演算法複雜度低:時間演算法複雜度 O(n),不需要額外空間。
缺點:可能出現溢位情況,對原陣列進行了修改。

解題思路2:

使用長度為n的記錄陣列 ,初始值設為0, 遍歷原陣列,每個數字都在記錄的陣列上+1,若記錄陣列上的該數字已經等於1,返回該數。

程式碼實現:

class Solution {
public:
    bool duplicate(int numbers[], int
length, int* duplication) { int temp[length]; memset(temp, 0, sizeof(temp)); // 區域性陣列沒有預設值,如果宣告的時候不定義,則會出現隨機數。 for(int i=0;i<length;i++){ temp[numbers[i]]++; if(temp[numbers[i]] >1){ *duplication = numbers[i]; return true; } } return false; } };

優點:時間演算法複雜度 O(n),不改變原陣列。
缺點:空間複雜度高,需要 O(n)

解題思路3

從頭到位掃描陣列,當掃描到下標為i的數字m時,如果是,則掃描下一個數字;如果不是,則那它和第m個數字比較:如果相等,就返回這個重複的數字,如果不相等,就把第i個數字和第m個數字交換。

例子:
{2,3,1,0,2,5,3}
第0個和第2個比較,交換
{1,3,2,0,2,5,3}
第0個和第1個比較,交換
{3,1,2,0,2,5,3}
第0個和第3個比較,交換
{0,1,2,3,2,5,3}
第0個是0,第1個是1,第2個是2,第3個是3
第4個是2,第2個也是2,找到重複數字,返回

程式碼實現:

class Solution {
public:
    bool duplicate(int numbers[], int length, int* duplication) { 
        if(numbers == nullptr || length <= 0)
            return false;
        for(int i=0;i<length;i++){
            if(numbers[i] < 0 || numbers[i] > length-1)
                return false;
        }
        for(int i=0;i<length;i++){            
            while(numbers[i]!=i){
                if(numbers[i] == numbers[numbers[i]]){
                    *duplication = numbers[i];
                    return true;
                }
                int tmp = numbers[i];
                numbers[i] = numbers[tmp];
                numbers[tmp] = tmp;
            }                                  
        }
        return false;       
    }
};

優點:演算法複雜度低:時間演算法複雜度 O(n),不需要額外空間;不會出現溢位情況。
缺點:對原陣列進行了修改。