leetcode解题报告(16):Move Zeroes
描述
Given an array nums, write a function to move all 0's to the end of it while maintaining the relative order of the non-zero elements.
For example, given nums = [0, 1, 0, 3, 12], after calling your function, nums should be [1, 3, 12, 0, 0].
Note:
You must do this in-place without making a copy of the array.
Minimize the total number of operations.
分析
遍历这个数组,判断当前元素是否为0,如果为0,就把0删除(erase),并且将0放到(push_back)最后。否则,将迭代器指向后一元素。
考虑到erase操作会使迭代器失效,因此让该函数返回一个迭代器,这样,执行删除元素的操作后,迭代器会自动指向被删除元素的后一元素(相当于把迭代器加1)。
对于把0压到数组末尾的操作,也会带来新的问题:数组的末尾元素不断更新,可能会导致迭代器永远到不了末尾。
为此,需要记录初始状态下数组的尾迭代器,然后在循环体里判断迭代器是否已到了这个尾迭代器,如果到了,直接break。
于是就有了下面的代码:
class Solution {
public:
void moveZeroes(vector<int>& nums) {
auto e = nums.end(); //保存初始状态下数组的尾迭代器
for(auto it = nums.begin(); it != nums.end();){
if(it != e){ //如果还没到达末尾
if(*it == 0){ //判断是否为0
it = nums.erase(it); //删除操作会更新当前的迭代器
nums.push_back(0); //push操作会改变末尾元素
}else //如果不为0,就让迭代器指向下一元素
++it;
}else //如果已到达初始状态下的末尾,就退出,避免进入死循环
break;
}
}
};
然而这段代码还是提示超时了。。。
看来还是naive啊,估计还是尾后迭代器失效,造成了一个死循环(不断地在删除0,又不断地把0添加到末尾,迭代器永远到不了最后)
机智如我,换成用int型变量判断是否到达末尾:
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int i = 0;
for(auto it = nums.begin(); it != nums.end();){
if(i != nums.size()){
if(*it == 0){
it = nums.erase(it);
nums.push_back(0);
}else
++it;
}else
break;
++i;
}
}
};
果然ac了。。。
心得
用迭代器遍历vector时,对于会更新、破坏迭代器的操作,一定要慎之又慎啊。