vector的remove和erase函式的區別
首先我們先來看一下兩個函式
iterator erase(iterator position);
iterator erase(iterator first, iterator last);
erase:
erase函式可以用於刪除vector容器中的一個或者一段元素,在刪除一個元素的時候,其引數為指向相應元素的迭代器,而在刪除一段元素的時候,引數為指向一段元素的開頭的迭代器以及指向結尾元素的下一個元素的迭代器。 在進行單個元素刪除後,傳入的迭代器指向不變,仍然指向被刪除元素的位置,而被刪除元素之後的所有元素都向前移動一位,也就是該迭代器實際上是指向了原來被刪除元素的下一個元素。其實vector還維持著一個last指標,開始的時候=end,隨著刪除,last前移,最終vector的size是last-begin,或者我們可以認為end值改變了,但最初傳入的end沒有變。
用例:
vector<int>::iterator itr = v.begin();
while (itr!=v.end())
{
if (*v==1)
{
v.erase(itr);
}
itr++;//這裡刪除後迭代器會更新出錯
}
以上程式碼是錯誤的,因為刪除一個元素之後,迭代器已經指向了被刪除元素的下一個元素,再進行itr++會出現野指標。也就是說veci.erase(iter)後,iter的狀態是不確定的,再進行++,豈有不崩潰的道理?!
正確程式碼為
vector<int>::iterator itr = v.begin(); while (itr!=v.end()) { if (*v==1) { itr=v.erase(itr); } else itr++; }
也就是說如果沒有erase操作,再將迭代器指向下一個元素。
刪除一段元素後,傳入的迭代器指向也是不變的,仍然指向原來傳進去時候的位置,修改的是刪除段後面的元素的位置。刪除段後面的元素都前移了。被刪除段用被刪除段的下一個元素代替了。
remove:
iterator remove(iterator first, iterator last,val);
remove函式會將範圍內所有等於val的值移動位置
STL中remove()只是將待刪除元素之後的元素移動到vector的前端,而不是刪除。若要真正移除,需要搭配使用erase()。
vector中的remove的作用是將等於value的元素放到vector的尾部
執行remove之後返回新的end()迭代器,但是不改變原來陣列的end()迭代器的值,將範圍內值等於val的元素用後一個元素替代。也就是原先陣列中新的end()至原end()範圍內的值仍為原來陣列的值(等於val的值),但是這部分狀態不可靠。begin()到新的end()這部分是不等於val的值。
區別:
也就是說erase和remove的區別在於執行函式之後返回值不同,被執行的vector的大小會不會改變
vector中erase的作用是刪除掉某個位置position或一段區域(begin, end)中的元素,減少其size,返回被刪除元素下一個元素的位置。
vector中remove的作用是將範圍內為val的值都remove到後面,返回新的end()值(非val部分的end),但傳入的原vector的end並沒有發生改變,因此size也就沒有變化
兩者結合應用:
刪除vector中值為x的元素
vec.erase(remove(vec.begin(),vec.end(),x),vec.end());
具體可參見leetcode26
重複元素只保留一個,對重複的原地移除。
思路:可以將重複的元素用一個特殊值替代,再統一刪除這個特殊值。
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size()==0)
return 0;
int res=1;
int flag=nums[0];
for(int i=1;i<nums.size();i++)
{
if(nums[i]==flag)
nums[i]=INT_MAX;
else
{
flag=nums[i];
}
}
nums.erase(remove(nums.begin(),nums.end(),INT_MAX),nums.end());
return nums.size();
}
};