leetcode【中等】34、在排序数组中查找元素的第一个和最后一个位置

在这里插入图片描述
思路:
要求复杂度nlogn,直接遍历复杂度是n,要用二分查找
注意边界上下取整!

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        if len(nums)==0:
            return [-1,-1]
        l=self.findleft(nums,target)
        if l==-1:
            return [-1,-1]
        r=self.findright(nums,target)
        return [l,r]

    def findleft(self,nums,target):
        left=0
        right=len(nums)-1
        while left<right:
            mid = left + (right - left) // 2#用/2会出现小数
            if nums[mid]<target:
                left=mid+1
            elif nums[mid]==target:#mid是一个目标,mid前可能还有
                right=mid
            else:
                #nums[mid]>target
                right=mid-1
        if nums[left] == target:
            return left
        else:
            return -1

    def findright(self,nums,target):
        left=0
        right=len(nums)-1
        while left<right:
            mid = left + (right - left + 1) // 2
            if nums[mid]>target:
                right=mid-1
            elif nums[mid]==target:#mid是一个目标,mid后可能还有
                left=mid
            else:
                #nums[mid]<target
                left=mid+1
        return left#如果l存在,那r肯定存在

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] res=new int[2];
        res[0]=-1;res[1]=-1;

        if(nums.length==0){
            return res;
        }
        int l=findleft(nums,target);
        if(l==-1){
            return res;
        }
        int r=findright(nums,target);
        res[0]=l;res[1]=r;
        return res;
    }
    public int findleft(int[] nums,int target){
        int left=0,right=nums.length-1;
        while(left<right){
            int mid=(left+right)/2;
            if(nums[mid]==target){
                right=mid;
            }
            else if(nums[mid]<target){
                left=mid+1;
            }
            else{
                right=mid-1;
            }
        }
        return nums[left]==target?left:-1;
    }

    public int findright(int[] nums,int target){
        int left=0,right=nums.length-1;
        while(left<right){
            int mid=(left+right+1)/2;
            if(nums[mid]==target){
                left=mid;
            }
            else if(nums[mid]<target){
                left=mid+1;
            }
            else{
                right=mid-1;
            }
        }
        return right;
    }
}

关于二分查找边界问题上下取整

  • right = midleft = mid + 1mid = left + (right - left) / 2;一定是配对出现的;
  • right = mid - 1left = midmid = left + (right - left + 1) /2; 一定是配对出现的。

整合一下比较规整的形式:

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] res=new int[2];
        res[0]=-1;res[1]=-1;

        if(nums.length==0) return res;

        int left=0,right=nums.length-1;
        while(left<right){
            int mid=(left+right)/2;
            if(target<=nums[mid]) right=mid;
            else left=mid+1;
        }

        if(nums[left]!=target) return res;
        int i=left,j=nums.length-1;
        while(i<j){
            int mid=(i+j+1)/2;
            if(target>=nums[mid]) i=mid;
            else j=mid-1;
        }
        res[0]=left;
        res[1]=j;
        return res;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值