Remove Duplicates from Sorted Array基本處理方法和集中優質解法解析

今天做了LeetCode的習題26,題目的目的是將排好序的序列中的重複元素去掉。

這道題的目的就是在排好序的數組中刪除重複元素。判斷元素是否重複不會太難,因爲數組是排好序的,難的是如何對重複元素進行操作。
最簡單的思路就是每發現一個重複元素就將後面的元素全部前移,但這對於長的數據來說是一種災難。
一定要找到更簡單的方法解決此問題。
還要注意約束條件是隻能使用線性空間解決此問題,其他想到的一些例如記錄重複數據序號的方法也是不可行的。

但後來發現自己想多了,題目給的是vector,還不如數組呢,因爲在確定自己代碼應該沒問題的時候報時間超限的問題。

代碼如下:

#include<vector>
class Solution {
public:
    int removeDuplicates(vector<int>& nums) {
		std::vector<int>::iterator it = nums.begin() ;
		while (it!=nums.end())
		{
			if (*it==*(it+1))
			{
				nums.erase(it);
			}
			it++;
		}
		return nums.size();
    }
};
看着很完美啊,但就是一直在報錯。
後來查閱得知:
如果在程序中對vector中的元素做了修改,添加或者刪除元素之後,迭代器就會失效,這時候就不要使用迭代器了。
想一下,如果把當前元素刪掉了,那麼當前元素就是之前的後一個元素,可我對每一個元素都進行了迭代器後移的操作,豈不是亂了套。

之後就沒注意了,不知道如何處理了。

再繼續查找資料,後來完美的解決了問題。

(查函數的頭文件傷不起啊!!!!!)

代碼如下:

int removeDuplicates(vector<int>& nums) {
    nums.erase(unique(nums.begin(), nums.end()), nums.end());
	return nums.size(); 
	}
注意就兩行,就兩行,就兩行!!!!

就這麼簡單。

unique函數會將所有重複的元素都放在隊列的後面,並且返回指向第一個重複元素的迭代器。

erase的作用是刪除從第一個重複元素開始到最後的函數,

最後直接返回vector的size。

感謝庫函數。


之後又想,如果直接返回size而不修改vector時如何寫,想了一下,代碼如下:

		std::vector<int>::iterator it = nums.begin();
		int sub = 0;
		while (it != nums.end()-1)//end指的是最後一位元素還是最後一位元素之後的元素不確定
		{
			if (*it == *(it + 1))
			{
				sub++;
			}
			it++;
		}
		return nums.size() - sub;


之後又查閱了其他方法,各種佩服啊。

1.反向思維。

先上代碼:

	int removeDuplicates(int A[], int n) {
		if (n < 2) return n;
		int id = 1;
		for (int i = 1; i < n; ++i)
		if (A[i] != A[i - 1]) A[id++] = A[i];
		return id;
	}

一開始對這個代碼特別不瞭解,所以覺得方法是錯的。後來還是仔細跑了一下,發現這個方法很精妙。

他的基本思路就是從第二個元素(序列號爲1)開始,依次和之前的元素比較,如果發現相同了,注意,這個時候是不會去處理的。如果發現不同,則說明這個元素肯定是在答案中的。以id另成爲一套計數,放入當前id處並且id++(最後返回的是id,總會比真正元素最後的序數大1,數組很顯然是從0開始計數,所以返回的就是size)。這樣說完應該還是不夠具體,拿一個小例子進行說明。

有此數組:{1, 2, 2, 3, 3, 4}

i:1 2 2 3 4 

id:1

此時爲初始化,雖然都是之的數組A,但是是兩個計數系統,一會就能發現差別。

i=1:

id=1,A[id]=A[i]=2

id=2

i: 1 2 2 3 4 

id: 1 2

i=2:

A[i]=A[i-1],不進行操作

i=3:

id=2,A[id]=A[i]=3

id=3

i: 1 2 2 3 4 

id: 1 2 3

      這裏就可以看出來算法的核心了。如果要是沒有重複的,就是自己等於自己,是沒有變化的。如果有重複的 ,就相當於將此元素向前移動重複元素個位置。

i=4:

id=3,A[id]=A[i]=4

id=4

i: 1 2 2 3 4 

id: 1 2 3 4

也就是說,每一次循環下來,id都是比結果的最後一個元素的序號大1,即最後元素的大小。

  應該說的夠清楚了。總算明白了。


同樣思路但是更好理解的做法如下:

int count = 0;
for(int i = 1; i < n; i++){
    if(A[i] == A[i-1]) count++;
    else A[i-count] = A[i];
}
return n-count;


其他方法都是大同小異的。

其實在解決這個問題的時候考慮的就是數組前移

這些方法非核心就是將每次發現重複元素都要進行的前移一位變爲總共爲O(n)次的前移若干位。
























發佈了36 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章