leetcode 双指针——283移动零

代码链接:https://github.com/xinhui1111/leetcode/blob/master/src/doublePoint.cpp
void moveZeroes(vector<int> &nums) void moveZeroes_Official(vector<int>& (nums))
想看最优的解法(这里的最优只是我已经会实现的最优)可以直接跳转到二、官方解法

零、题目说明

在这里插入图片描述
两个要求:

  1. 将零放在后面;
  2. 非零的相对位置不能变;

一、自己的解法

最开始错误的解法——遇0首尾互换,相对位置被打乱

原理
首先我是想着直接将双指针一个放在第一个位置上,一个放在最后一个位置,然后两者进行转换,遍历完整个数组。
在这里插入图片描述

实现代码

void moveZeroes(vector<int> &nums) {
    //这种方法把相对位置变了
    //可以从前往后进行推,遇到0就将其放在最后,并且放了之后指向最后的位置就向前移动一位
    int left{0};
    int right{static_cast<int>(nums.size()-1)};
    //前后两个指针,前面一个一步步向后移动,当遇到0就与最后的进行转换,转换了之后后面的指针也要向前移动一个,非0就向后进行移动,
    while(left<right){
        if(nums[left]==0){
            //将这个位置和最后一个位置的数进行互换
            if(nums[right]!=0){
                //进行互换
                int temp{0};
                temp=nums[left];
                nums[left]=nums[right];
                nums[right]=temp;
            }
            right--;
        }
        left++;

    }
}

优劣
放入官方代码中,检查是否正确:
在这里插入图片描述
可以看到是因为顺序不对,这是因为首尾互换打乱了顺序。我们拿出前面的原理图就可以看出来,因为前面没有特别留意到这里顺序被打乱了:
在这里插入图片描述
比如这的12就因为在最后,与第一个就换了位置,换到了第一的位置,那么就和之前的相对位置不一样了。

正确的解法——每次遇到0向前平移,效率不高

原理
为了保证相对位置不变,首先想到的最简单的办法就是遇到0的时候就把0放在最后,然后0后面的元素都向前移动一位,同时两个指针位置也要改变。
在这里插入图片描述
代码

void moveZeroes(vector<int> &nums) {
    int left{0};
    int right{static_cast<int>(nums.size()-1)};

    while (left<right){
        if(nums[left]==0){
            //就把left后面的全部往前移动
            for(int i=left;i<right;i++){
                nums[i]=nums[i+1];
            }
            nums[right]=0;
            right--;
        }
        else
            left++;
    }

}

优劣
将其提交,可以看到代码效率很低:
在这里插入图片描述

二、官方的解法

原理
将非零值一步步提到最前面,所以关键是移动右指针,遇到非零就把它换到前面,并且是以类似尾插针的方式:
在这里插入图片描述
代码实现

/*
 * 借鉴了官方的解法
 * 将指针放在相邻的位置,如果遇到是0的时候,就把0放在前面
 */
void moveZeroes_Official(vector<int>& (nums)){
    int left{0};
    int right{0};
    while (right<nums.size()){
        if(nums[right]){
            //将left与right进行互换
            int temp{0};
            temp=nums[left];
            nums[left]=nums[right];
            nums[right]=temp;

            left++;
        }
        right++;
    }
}

优劣
将其提交,看到效率不错:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值