1. 程式人生 > >LeetCode(26)Remove Duplicates From Sorted Array

LeetCode(26)Remove Duplicates From Sorted Array

題目如下

Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length.
Do not allocate extra space for another array, you must do this in place with constant memory.
For example,
Given input array A = [1,1,2],
Your function should return length = 2, and A is now [1,2].

題目分析

和上面一道題目比較類似。但是本題在題目中明確要求,不僅要返回濾重後的length而且要保證原陣列的前length個數是濾重後的結果。我的想法比較直觀,直接遍歷陣列,針對每個元素,把這個元素和它右邊的元素進行兩兩比較。如果不相同則向右繼續進行比較,如果相同則把重複的元素刪除並且進行新的比較。因為是在陣列中刪除,所以每次都需要把待刪除元素的右側的元素逐個地左移,效率較低。

//88ms
class Solution {
public:
    int removeDuplicates(int A[], int n) {
        for(int i=0;i<n-1;i++){
            if(A[i]==A[i+1]){
                for(int j=i+1;j<n-1;j++)
                    A[j]=A[j+1];
                n--;
                i--;
            }
        }
        return n;
    }
};

為了提高效率,需要避免把待刪除的元素逐個進行左移。為了實現這一點。可以不斷地把不需要刪除的元素依次從左到右放入一個新陣列。實際上由於新陣列是濾重後的陣列,總是比原陣列短或者相等。所以可以共用新陣列和原陣列的空間。也就是,對A陣列,一邊檢查沒兩個元素是否相等,一邊生成新陣列。以[1,1,2,3,4,4,4,]為例。

起始狀態,先把第0個元素放入新陣列,也就是把1放入新陣列。然後開始比較第0個元素和第1個元素。也就是比較1和1.

1和1比較,二者相等,所以不放數字進入新陣列,新陣列中下一個待放入的下標為1。

1和2比較,二者不等,所以把2放入新陣列,放入下標為1的地方,新陣列中下一個待放入的下標為2。

2和3比較,二者不等,所以把3放入新陣列,放入下標為2的地方,新陣列中下一個待放入的下標為3。

3和4比較,二者不等,所以把4放入新陣列,放入下標為3的地方,新陣列中下一個待放入的下標為4。

4和4比較,二者相等,所以不放數字進入新陣列,比較下一個數字,也就是第3個4.

4和4比較,二者相等,所以不放數字進入新陣列,比較下一個數字,發現到達陣列結尾,結束。

程式碼如下

// 80ms
class Solution {
public:
    int removeDuplicates(int A[], int n) {
        if(n<=0)
            return 0;
        int i=0;
        int j=i+1;
        while(j<n){
            if(A[i]!=A[j]){
                A[i+1]=A[j];
                i++;
                j++;
            }else{
                j++;
            }
        }
        return i+1;
    }
};
經過更改後,理論上時間複雜度由O(N²)變化為了O(N)。實際上測試表明,只是從88ms降低到了80ms。。。。
於是網上搜之,看到leetcode官網上一個更簡潔的寫法。思路和上面第2種一樣,但是語言更簡潔。測試了一下,這個通過大集合只需要56ms.
//56ms
class Solution {
public:
    int removeDuplicates(int A[], int n) {
        if (n < 2) return n;
        int len = 1;
        for(int i = 1; i < n; ++i) {
            if(A[i] != A[len - 1]) {
                A[len++] = A[i];
            }
        }
        return len;
    }
};

update: 2014-10-09

在原陣列的基礎上從左到右生成新陣列,用keep_index表示留存下來的數,也就是新陣列的下標。用index表示原陣列的下標。思路和這道remove element很像。

class Solution {
public:
    int removeDuplicates(int A[], int n) {
        if (n < 1) return n;
        int keep_index = 0;
        int index = 1;
        while (index < n) {
            if (A[keep_index] != A[index]) { 
                ++keep_index;
                A[keep_index] = A[index];
            }
            ++index;
        }
        return keep_index + 1;
    }
};

update: 2015-01-10

//33ms
class Solution {
public:
    int removeDuplicates(int A[], int n) {
        int i = 0, j = 0;
        while (i < n && j < n) {
            if (j + 1 < n && A[j] == A[j + 1]) {
                A[i] = A[j];
                ++i;
                while (A[j] == A[i - 1])
                    ++j;
            }else {
                A[i] = A[j];
                ++i;
                ++j;
            }
        }
        return i;
    }
};