283. 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全部放到最后,其他的按照原来的顺序排到前面去,不能拷贝数组。

刚开始我是想法就是用一个zero来记录数组中的最后0元素的下标,用num记录非0元素的下标。如果num比zero大的话,说明后面的一个非0的需要放到前面来,让其交换即可,然后让zero寻找下一个非0位置。

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        int zero = -1;//表示最后一个0的下标
        int num = 0;//表示非0的下标
        for(int i=0; i < nums.size() ;i++) {
            if(nums[i] != 0) {//如果此时不等于0,先用num记录下来此刻的坐标
                //cout << "此刻不等于0:" << i << endl;
                num = i;
            }

            if(zero == -1 && nums[i] == 0) {
                //cout << "找到数组中的第一个0下标:" << i << endl;
                zero = i;
            }

            if(zero != -1) {
                if(num > zero) {//如果num大于zero,说明后面有一个非0,此刻需要交换位置了,并且让zero等于自后一个0的下标
                    //cout << "发生交换的两个下标为,非0:" << num << ",0:" << zero << endl;
                    swap(nums[zero],nums[num]);
                    //cout << "交换完之后zero下标的元素为:" << nums[zero] << ",num下标的元素为:" << nums[num] << endl;
                    while(nums[zero] != 0) {
                        //cout << "这里的zero不等于0,所以需要向后查找,此刻zero为:" << zero << endl;
                        zero++;
                        //i++;
                    }
                    if(zero>=nums.size()) {//说明已经完成了
                        break;
                    }
                }
            }
        }

        //for(int i=0;i<nums.size();i++) {
            //cout << nums[i] << ",";
        //}

    }
};

不过这种的效率不高,后来看了看靠前的做法,发现没必要记录非0和0的下标。如果发现有非0元素直接判断是否需要交换就可以了。同样的也是两个标志i和j,两个都从零开始,一个i循环自增,如果发现此刻的元素非0,则判断当前的坐标i和另一个坐标j是否相等,相等的话说明此刻j也是处于非0位置的,就让j向后移动一位。不相等的话j一定是处于0的位置的,发生交换即可。

其中只有一点需要解释,为什么i和j不相等的话,j一定处于0位置。

假设数组是这样的:[1,2,0,0,5]。

刚开始i和j都为0,使用i开始遍历:

i = 0,发现此刻i的位置上非0,则判断此刻i和j是否相等,发现相等则说明j也是处于非0元素,就让它向后移动一位,j=1。

i = 1,此刻非0,判断i和j相等,说明j处于非0元素,则向后移动一位,j = 2。

i = 2,此刻为0,不进行计算,直接向后移动,而此刻的j就处于0位置。

i = 3,向后移动。

i = 4,此刻非0,i位置上的与j位置上的进行交换。

说白了,如果当前元素非0,那么i和j都共同的向后移动。如果当前的是0,仅仅i向后移动,所以j就停留在了0的位置。

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        for(int i=0,j=0;i<nums.size();i++) {
            if(nums[i]) {//如果此时不等于0,进行计算
                if(i!=j) {//相等的话说明j此刻也是处于一个非0位置
                    swap(nums[i],nums[j]);
                }
                j++;//如果发生交换了需要加一,如果不交换也需要加一
            }
        }

        //for(int i=0;i<nums.size();i++) {
            //cout << nums[i] << ",";
        //}
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值