LeetCode 34. Find First and Last Position of Element in Sorted Array

题目:Given an array of integers nums sorted in ascending order, find the starting and ending position of a given target value. Your algorithm's runtime complexity must be in the order of O(log n). If the target is not found in the array, return [-1, -1].

代码如下:

class Solution:
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        if len(nums)==0:
            return [-1,-1]
        start,end=-1,-1
        low,high=0,len(nums)-1
        while low<=high:
            mid=(low+high)//2
            if nums[mid]<target:
                low=mid+1
            elif nums[mid]>target:
                high=mid-1
            else:
                start,end=mid,mid
                break
        else:
            return [start,end]
        
        #先求start
        tmp_high=start
        while low<tmp_high:
            mid=(low+tmp_high)//2
            if nums[mid]==target:
                tmp_high=mid
            else:
                low=mid+1
        start=low
        #求end
        tmp_low=end
        while tmp_low<high:
            mid=(tmp_low+high+1)//2
            if nums[mid]==target:
                tmp_low=mid
            else:
                high=mid-1
        end=tmp_low
        return [start,end]

具体思路如下:

首先,题目对时间复杂度有要求,这题还是查找,而查找算法中满足logn复杂度的有折半查找。所以代码中第一段while结构基本与这般查找相同.具体判断了三种情况:

当nums[mid]<target时,所有的target只能在mid的右侧,所以low=mid+1

当nums[mid]>target时,所有的target只能在mid的左侧,所有high=mid-1

而当nums[mid]==target时,target的开始和结束位置可能在mid的两侧。而要找到target的开始和结束的位置,在midd的两侧都有进行查找,所以这个时候只能跳出当前的while循环,对mid两侧的两段有序序列分别进行查找。(mid左右两侧都是有序序列,同样可以利用折半查找。)

else子句处理target不在nums序列中的情况,直接return [-1,-1]

下面进入两个while循环。

第一个while循环求start。在这个循环中所做的工作就是将low不断地想tmp_high靠近。

当nums[mid]=target时,将tmp_high放置到mid的位置。这里要说明一下,因为在寻找start的时候,我们实际要找的是索引值最小的start,所以我们要保证low和tmp_high的两个索引对应的值必须有一个一直为target,否则在循环结束的时候没办法确定target的开始索引。

第二个while循环去end。在这个循环中所有的工作就是不断移动high。大体的思想与前一个whild循环类似。我重点要讲的是下面这个问题。下面贴出的代码是我第一次的代码版本,这两段代码的区别在于mid值的计算,在求start的循环中,mid的计算是向下取整,而在这里则是向上取整。

        while tmp_low<high:
            mid=(tmp_low+high)//2
            if nums[mid]==target:
                tmp_low=mid
            else:
                high=mid-1
        end=tmp_low

我在执行这个版本的代码时,提示超时。也就意味着我这段代码导致了死循环。这个死循环的原因主要是这个代码无法处理一下情况:

在这种情况下,tmp_low永远没有办法等于high,mid用于等于tmp_low,所以不会结束循环,tmp_low也没有定位到target的结束索引,所以在最终提交的代码版本里改成了向上取整。循环既可以正常结束,也能正常定位到结束索引。

在求start的while循环里,出现这种情况时,high会向low移动,所以不会死循环,也就能正常定位开始索引。以上就是对于这一题的总结。如有误,请纠正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值