刷题篇--二分查找

刷题篇–二分查找

思路很简单,细节是魔鬼。----二分查找

你真的了解二分查找吗?一般情况下二分查找要找到给的目标值,若没有找到则返回-1,这是传统技能。但是肯定会有幺蛾子出现,比如查找出数组中第一个出现或最后一个出现的位置、数组中有多少个要查找的元素等。
该文章将会梳理二分查找的一些基本内容,如果理解不够透彻,就直接记模板。

1.基本二分查找

nums = [3,4,5,7,8,8,8,10]
target = 5

low, high = 0, len(nums)-1   #赋值左右指针
while low <= high:
	mid = low + (high - low) // 2  #这种写法是为了防止low+high过大溢出
	if nums[mid] == target:
		print(mid)
		break
	elif nums[mid] < target:
		low = mid + 1
	else:
		high = mid - 1

这里要注意下找不到的情况,循环条件是low<=high,未找到的话终止条件肯定是low>high。实际上此时如果target不大于列表最大值,low也就是离target最近的大于它的那个位置;如果大于target,low最后应是len(nums)-1,这样讨论起来有些乱,所以索性我们直接再延申出两个关于上下界的模板。

2.寻找下界

前面已经说过,如果直接找某个target,上面的模板已经足够了。但是会出现一些变化的问题,如找到上下界等问题。这时讨论较复杂,所以我们直接写模板。

nums = [3,4,5,7,8,8,8,10]
target = 8

low, high = 0, len(nums)   
while low < high:
    mid = low + (high - low) // 2
    if nums[mid] < target:
        low = mid + 1
    else:
        high = mid
#low的结果为4,也就是它的下界(查找到的第一个target)

再来讨论一下low和high的问题,循环条件是low<high,最后退出循环时low=high,所以我们不用再纠结low和high的问题,因为最后他们是相同的。
如果low等于len(nums),或对应位置索引不等于target,则未找到。

if low == len(nums) or nums[low] != target: return False

再看一下找到target与未找到的区别

  • 能够找到target,则low为找到的第一个值
  • 如果未找到,则low为大于target的第一个值,如target = 6则返回low=3;target = 16(target>max(nums)) 则返回low=len(nums)

3.寻找上界

nums = [3,4,5,7,8,8,8,10]
target = 8

low, high = 0, len(nums)   
while low < high:
    mid = low + (high - low) // 2
    if nums[mid] <= target:
        low = mid + 1
    else:
        high = mid
#low的结果为7,也就是它的上界(查找到的最后一个target+1)

看一下找到target与未找到的区别

  • 能够找到target,则low为找到的最后一个值加1
  • 如果未找到,则low为大于target的第一个值,如target = 6则返回low=3;target = 16(target>=max(nums)) 则返回low=len(nums)

4.刷题题目

  1. leetcode34,在排序数组中查找元素的第一个和最后一个位置。
    思路:该题可通过两次二分查找,找到上界和下界,得到第一个位置和最后一个位置。
def search_range(nums, target):
    low, high = 0, len(nums)
    while low < high:
        mid = low + (high - low) // 2
        if nums[mid] < target:
            low = mid + 1
        else:
            high = mid
    if low == len(nums) or nums[low] != target: 
    	return [-1,-1]  #判断是否在nums中,未找到就不需要执行下一步了
    idx = low

    low, high = 0, len(nums)
    while low < high:
        mid = low + (high - low) // 2
        if nums[mid] <= target:
            low = mid + 1
        else:
            high = mid    
    return [idx, low-1]
  1. leetcode69,x的平方根
    该题解题方法较多,在这里使用二分法。相当于找到下界。
def my_sqrt(x):
    l, r = 1, x+1  #此处位置即对应值
    while l < r:
        mid = (l+r) // 2
        if mid * mid <= x:
            l = mid + 1
        else:
            r = mid
    return l-1

如果我们不使用上下界模板,使用基础的二分查找,则代码如下

def mySqrt(self, x):
    l, r = 1, x
    while l <= r:
        mid = (l+r) // 2
        if mid * mid == x:
            return mid
        elif mid * mid < x:
            l = mid + 1
        else:
            r = mid - 1
    return min(l, r)

此时需要讨论low和high的关系,在这里去出l和r的最小值。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值