leetcode35:搜索插入位置

同样是对于区间的处理问题,可以参照上一题704的思路,稍加进行修改

class Solution {
    public int searchInsert(int[] nums, int target) {
        int left = 0;
        int right = nums.length-1;
        int pos = left+(right-left)/2;
        //先排除在序列外的数
        if(target<nums[0]){
            return 0;
        }else if(target>nums[right]){
            return nums.length;
        }
        //二分查找,如果在序列以内,直接返回
        while(left<=right){
            pos = left+(right-left)/2;
            if(target>nums[pos]){
                left=pos+1;
            }else if(target<nums[pos]){
                right=pos-1;
            }else{
                return pos;
            }
        }
        //退出while循环时,表明这个数出现在了pos两边而不在序列内部
        if(target<nums[pos]){
            return pos;
        }else{
            return pos+1;
        }
        //或者直接写为return right+1
    }
}

由于是右闭区间,所以结果直接返回right+1,可以不用pos判断

参考代码随想录网站,还有其余做法,可以不用搜寻第一次出现位置,直接查找左右区间

方法一(有修改,网站代码和我实际验证不同)

这个做法差不多是,从中间往两头逼近端点,寻找的边界包含target

class Solution {
    public int[] searchRange(int[] nums, int target) {
        //大体思想还是使用二分查找
        //1.该元素在数组范围外
        //2.该元素在数组范围中,但不在数组内
        //3.该元素在数组内
        int lpos=findleft(nums,target);
        int rpos=findright(nums,target);
        return new int[]{lpos,rpos};
    }
    int findleft(int[]nums,int target){//此处寻找的边界包含=target
        int left=0;
        int right=nums.length-1;
        int middle=left+(right-left)/2;
        while(left<=right){
            middle=left+(right-left)/2;
            if(nums[middle]>=target){
                right=middle-1;
            }else{
                left=middle+1;
            }
        }
        //找到最左端点时,right左移,此时left为有效位置
        if(left>=0&&left<nums.length&&nums[left]==target){//情况三
            return left;
        }
        return -1;//情况一和情况二
    }
    int findright(int[]nums,int target){
        int left=0;
        int right=nums.length-1;
        int middle=left+(right-left)/2;
        while(left<=right){
            middle=left+(right-left)/2;
            if(nums[middle]<=target){
                left=middle+1;
            }else{
                right=middle-1;
            }
        }
        //当找到右端点时,left右移,right值有效
        if(right>=0&&right<nums.length&&nums[right]==target){//情况三
            return right;
        }        
        return -1;//情况一和情况二
    }
}

方法二  这个做法等于是从两边往中间逼近,寻找边界不包含target

class Solution {
    public int[] searchRange(int[] nums, int target) {
        //情况一,元素在数组范围外,lpos和rpos都会返回-2
        //情况二,元素在数组范围内,但不在数组内,
        //情况三,元素在数组内,应该返回lpos+1,rpos-1
        int lpos=findleft(nums,target);
        int rpos=findright(nums,target);
        if(lpos==-2||rpos==-2){
            return new int[]{-1,-1};
        }
        if(rpos-lpos>1){
            return new int[]{lpos+1,rpos-1};
        }
        return new int[]{-1,-1};
    }
    int findleft(int[]nums,int target){
        int left=0;
        int right=nums.length-1;
        int middle=left+(right-left)/2;
        int lpos=-2;
        while(left<=right){
            middle=(left+right)/2;
            if(nums[middle]<target){
                left=middle+1;
            }else{
                right=middle-1;
                lpos=right;//当逼近到最左位置时候,lpos会在目标元素的左边
            }
        }
        return lpos;
    }
    int findright(int[]nums,int target){
        int left=0;
        int right=nums.length-1;
        int middle=(left+right)/2;
        int rpos=-2;
        while(left<=right){
            middle=(left+right)/2;
            if(nums[middle]>target){
                right=middle-1;
            }else{
                left=middle+1;
                rpos=left;
            }
        }
        return rpos;
    }
}

好像可以把左右边界放到一个函数里解决,但是,让我练练ORZ 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值