1. 程式人生 > >LeetCode-27 移除元素->竟然擊敗了100%使用者 (內附vector中erase的使用方法)

LeetCode-27 移除元素->竟然擊敗了100%使用者 (內附vector中erase的使用方法)

題目描述

給定一個數組 nums 和一個值 val,你需要原地移除所有數值等於 val 的元素,返回移除後陣列的新長度。

不要使用額外的陣列空間,你必須在原地修改輸入陣列並在使用 O(1) 額外空間的條件下完成。

元素的順序可以改變。你不需要考慮陣列中超出新長度後面的元素。

示例 1:

給定 nums = [3,2,2,3], val = 3,

函式應該返回新的長度 2, 並且 nums 中的前兩個元素均為 2。

你不需要考慮陣列中超出新長度後面的元素。

示例 2:

給定 nums = [0,1,2,2,3,0,4,2]
, val = 2, 函式應該返回新的長度 5, 並且 nums 中的前五個元素為 0, 1, 3, 0, 4。 注意這五個元素可為任意順序。 你不需要考慮陣列中超出新長度後面的元素。

說明:

為什麼返回數值是整數,但輸出的答案是陣列呢?

請注意,輸入陣列是以“引用”方式傳遞的,這意味著在函式裡修改輸入陣列對於呼叫者是可見的。

你可以想象內部操作如下:

// nums 是以“引用”方式傳遞的。也就是說,不對實參作任何拷貝
int len = removeElement(nums, val);

// 在函式裡修改輸入陣列對於呼叫者是可見的。
// 根據你的函式返回的長度, 它會打印出陣列中該長度範圍內的所有元素。
for (int i = 0; i < len; i++) {
    print(nums[i]);
}

解決方案

我就直接上程式碼吧,不知道怎麼回事,Leetcode竟然說我的程式碼擊敗了100.00%的使用者(注意部落格釋出時間,有可能後來人有更好的方法,這樣就不是擊敗100%了。哈哈,所以別噴我哈!),不可思議。題目雖然簡單,但是裡面C++中STL中的某些方法還是很有必要好好學習的,學好了並掌握了這些STL方法,在以後的工作必能事半功倍。先看程式碼。然後說明一下原理和方法細節。

好了,不裝ACD了,下面就看程式碼吧!

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        auto ibegin=nums.begin();
        auto iend=nums.end();
        while(ibegin!=iend)
        {
            if(*ibegin==val)
            {
                ibegin=nums.erase(ibegin);
                iend=nums.end();//一定要注意,當刪除了一個元素之後,這個vector的元素已經向前移動一個元素,但是呢end()指標發生了變化。
            }
            else
                ibegin++;
        }
        
        return nums.size();
        
    }
};

原理以及方法

為了更好的移除指定內容的vector元素,肯定需要進行一次迭代,所以我定義兩個迭代器。

但是應該注意erase的使用方法,為了做這個題,我甚至還查看了官方vector的使用說明(見下圖):

 

可以看出他有兩個使用方法:

  1. 給一個迭代器,讓他刪除指定元素
  2. 給一個迭代器的範圍,他會刪除範圍內的所有元素。

 

可以看出來,需要指出刪除的迭代器指標,然後返回值是當前所刪除元素的下一個位置。所以呢一旦你進行了這個操作,就不要再自己ibegin++了,直接將返回值賦給ibegin就可以了。(我們使用1的方法。)

ibegin=nums.erase(ibegin);

還有一點需要注意:

iend=nums.end();//一定要注意,當刪除了一個元素之後,這個vector的元素已經向前移動一個元素,但是呢end()指標發生了變化。

因為刪除了vector中的元素,這時候最後一個元素就移動了,這樣iend所指的東西就不知道是什麼地方了,因此需要實時更新最後一個指標(別看這個問題很小,花我好多時間除錯。)所以凡是涉及到容器增刪的時候,迭代器範圍指標,務必要進行實時更新。

這就是我的總結,希望大家多多關注,多多交流。