每日一题-移除元素

盲猜封面会被吞 o(一︿一+)o(不吞我就发评论区)

今天要写的是力扣上非常经典的双指针题目,原地移除元素,先看题目:

法一,最简单直接的思路,其实就是左右指针各遍历一遍数组,将非val从第一个往后赋值,这样还能保证元素相对顺序不变.不过多解释,代码相对简单:

class Solution {
    public static int removeElement(int[] nums, int val) {
        int left = 0;
        for(int i = 0;i<nums.length;i++){
            if(nums[i] != val){
                nums[left++]=nums[i];   //右指针的值不等于val时赋给左指针;
            }
        }
        return left;
    }
}

法二,其实我们可以使右指针去寻找非val,然后赋值给值为val的左指针,这种思路对于要移除的val相对少时,效率要比法一高一些,左指针从0开始向右移动,右指针从右向左,这样只需要遍历一次数组即可.

我这个思路看起来很好,但是实际上我写的时候很费劲,各种查漏补缺调bug,我还纳闷明明很简洁的思路就是会出现这么多bug.以下是我的代码:

class Solution {
    public static int removeElement(int[] nums, int val) {
        int left = 0,right = nums.length-1;
        while(left <= right){
            while(nums[left] != val&&left < right){
                left++;
            }
            while(nums[right] == val&&left < right){
                right--;
            }
            if(nums[left] != val&&left == right)  //这里额外的两个if是为了处理一些实例情况
                return left + 1;                 //造成代码冗余
            if(nums[left] == val&&left == right)
                return left;
            nums[left++] = nums[right--];         //两个指针同时动,不是好选择
        }
        return left;
    }
}

这段代码我写的并不满意,很不够简洁,我去看了一眼答案,和我相似的思路,却比我简洁许多,我仔细进行了比对,发现根本原因在于我让两个指针同时动,这样对循环过程控制的不够细,导致每一次大循环都走得很快,很容易出现细节问题,而如果一次只动一个指针,那么控制起来就会相对简单很多,而且这样也只需要遍历一次.以下是官方给的答案:

class Solution {
    public static int removeElement(int[] nums, int val) {
        int left = 0;
        int right = nums.length-1;
        while(left <= right){
            if(nums[left]==val){
                nums[left] = nums[right--];
            }else{
                left++;
            }
        }
        return left;
    }
}

官方答案实际上忽略了右指针的值直接赋给左指针,因为这么写可以直接检查给过来的值是否为val,如果是val则left不动,继续原地赋值.

好了,今天的题解就分享到这里,这道题还是非常经典的,建议大家多做几次,并且用多种思路解决,有助于我们加强对指针思想的理解与运用.

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值