Day2 代码随想录(1刷) 双指针

文章介绍了如何使用二分查找优化在排序数组中查找元素的第一个和最后一个位置,以及移除数组中特定元素的方法,强调了边界条件和二分查找策略在提高效率中的关键作用。
摘要由CSDN通过智能技术生成

704 二分查找、

状态:完成

该题是一道经典的二分查找问题,时间复杂度O(logn)。循环条件中的left<=right是否取等是关键,边界条件的判定看取等之后进循环还有意义吗,取等之后是有意义的因为遍历没有遍历过。三种情况的取值也是关键。

public int search(int[] nums, int target) {
        int left=0;
        int right=nums.length-1;
        int mid = left + (right-left)/2;
        //这里取等表示left==right时是有意义的
        while(left<=right){
            mid = left + (right-left)/2;
            //先判断一下target是不是nums[left]跟nums[right]
            if(target==nums[left]&&target==nums[right]){
                return target==nums[left]?left:right;
            }
            //分三种情况 target大于nums[mid],target小于,target等于
            if(target>nums[mid]){
                left=mid+1;//mid肯定不是target
            }else if(target<nums[mid]){
                right=mid-1;//mid肯定不是target
            }else if(target==nums[mid]){
                return mid;
            }
        }
        return -1;
}

34.在排序数组中查找元素的第一个和最后一个位置

状态:完成

一开始使用从两边向中间找的方式险些超时,效率很差劲。

public int[] searchRange(int[] nums, int target) {
        int left=0;
        int right=nums.length-1;
        while(left<=right){
            if(nums[left]!=target){
                left++;
            }
            if(nums[right]!=target){
                right--;
            }
            if(right<0||left>nums.length-1) break;
            if(nums[right]==target&&nums[left]==target){
                return new int[]{left,right};
            }
        }
        return new int[]{-1,-1};
}

然后我先有二分法找到target值,然后向这个值的两端找,效率也不高不过比上面的好

public int[] searchRange(int[] nums, int target) {
        if(nums.length==0) return new int[]{-1,-1};
        int left=0;
        int right=nums.length-1;
        int mid=0;
        while(left<=right){
            mid = left + (right-left)/2;
            //先判断一下target是不是nums[left]跟nums[right]
            if(target==nums[left]&&target==nums[right]){
                mid=target==nums[left]?left:right;
                break;
            }
            //分三种情况 target大于nums[mid],target小于,target等于
            if(target>nums[mid]){
                left=mid+1;//mid肯定不是target
            }else if(target<nums[mid]){
                right=mid-1;//mid肯定不是target
            }else if(target==nums[mid]){
                break;
            }
        }
        if(nums[mid]!=target) return new int[]{-1,-1};
        left=mid;
        right=mid;
        for(int i=1;i<=mid;i++){
            if(nums[mid-i]!=target&&nums[mid-i+1]==target){
                left=mid-i+1;
                break;
            }else if(nums[mid-i]==target){
                left=mid-i;
            }
        }
        for(int i=1;i<=nums.length-1-mid;i++){
            if(nums[mid+i]!=target&&nums[mid+i-1]==target){
                right=mid+i-1;
                break;
            }else if(nums[mid+i]==target){
                right=mid+i;
            }
        }

        return new int[]{left,right};
    }

然后看了解析发现可以直接用二分法找到两侧的端点这个方法很好,以找左边界为例,使用二分法去查找,如果mid比target小左边则left=mid+1,如果mid等于target则right=mid,就这样不停地移动最后得到的left就是左边的边界点。

27. 移除元素z

状态:完成

因为答案就看前几位,只要把val移到数组末尾就行了。使用两个指针,一个指向答案数组结尾,一个不停地向前移动。当nums[left]不是val时就移动left,left就像个扫地机一样,只要是val他就停下来做交换,把它向后移。

public int removeElement(int[] nums, int val) {
        int len=nums.length;
        int left=0;
        int right=0;
        for(right=0;right<nums.length;right++){
            int temp=nums[right];
            nums[right]=nums[left];
            nums[left]=temp;
            if(nums[left]!=val) left++;
        }
        return left;
}

  • 11
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值