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时,对于会更新、破坏迭代器的操作,一定要慎之又慎啊。

posted @ 2017-05-01 11:39  larryking  阅读(211)  评论(0编辑  收藏  举报