二分查找经典问题

二分答案

需要找一个整数,我们知道它的最小和最大值,用二分法最后找到这个数。

69.X的平方根

1.如果向下 mid=l+(r-l)/2,最后得到的是大于等于x最小的数
如果是向上 mid=l+(r-l)/2+1 才是得到小于等于x最大的数
2.如果判断条件写成:
在这里插入图片描述
会发生溢出
在这里插入图片描述
需要改成
在这里插入图片描述

287.寻找重复数

数组不是有序的。
思路:
在重复数出现之前,小于等于数字i的数肯定小于等于i个。
在重复数出现之后,小于等于数字i的数肯定大于i个。
多的计算量就是要算,小于等于这个数总量有多少(O(n))。

在这里插入图片描述

1300.转变数组后最接近目标值的数组和。

先找数组规律。这个value最小为0,因为所有大于0的都会变成0,最后这个数组的和为0。之后是单调递增,value越大,和会越大。当value等于数组中最大的数的时候,value再增加,数组和也不会变了。

所以左边界l=0,右边界r=arr.max。
在这里插入图片描述

进行二分查找,结果肯定是要么比目标数大一点,要么比目标数小一点,必然在这两个中间一个。
我们先设置一个ans是在比目标小一点的那个,然后得出后,直接与下一个比较绝对值,最后得出结果。
在这里插入图片描述多余的计算是要每次算value更新后的和。
在这里插入图片描述时间复杂度:
设最大数为C,因此二分查找复杂度为O(log C),每次查找还要遍历数组一次,
O(N log C)
空间复杂度:
O(1)

判别条件复杂的二分查找问题

之前的二分答案,是单调的,因此好判断趋势。但是一些问题中的目标变量不好判断,但是与之相关的另一个变量,所以会用一个判别函数。

875.爱吃香蕉的珂珂

和1300类似。先分析左边界和右边界。左边界为1,也就是至少每小时吃一根。
考虑到H的范围:在这里插入图片描述如果H最小为堆数,那么要保证每一堆都能在一个小时内被吃完。
所以右边界为max(piles)。
我们是用总时间和H比较,S>H,说明速度慢了,K应该在右区间。S<H说明速度快了,K应该在左区间。
在这里插入图片描述

值得注意的是,这里有重复值。也就是说也许取4或者5,S值不变。但是我们需要小的那个。因此 S==H时,不忙着退出,而是r–,相当于向左范围靠近。
在这里插入图片描述最后得到的那个数就是最小满足要求的值。
时间复杂度:
O(NlogW) 其中W为数组中最大值,N为数组数
空间复杂度:
O(1)

410. 分割数组的最大值

用二分法。也是先找左右边界。左边界应该为数组中最大的数,右边界是整个数组的和(这种情况m=1)
在这里插入图片描述

然后挨个比较,这个数是否能满足分成m份,如果不能满足,取右区间,说明这个数还不够大。如果满足就取左区间,说明我们还可以尝试更小的数。
在这里插入图片描述如何检查该数是否符合分堆要求?
直接数,一旦和大于这个数,那么堆数+1,起始堆为1,找到一个分界点,从一堆变成两堆。
在这里插入图片描述如果堆数比指定堆数多,说明不能满足。如果比指定的少,最大的那个还可以再分,说明可以满足。
时间复杂度:
O(nlog(sum-max))
空间复杂度:
O(1)

1011. 在 D 天内送达包裹的能力

和上面的分割最大数组一模一样的解法。

1482 .制作 m 束花所需的最少天数

取的这个数,小于它的天数都会开花。右区间为数组中最大值,就是整个数组花都开了。左区间取1。
在这里插入图片描述
如果满足堆数,那么我们的天数还可以少,否则就是要增加天数。
在这里插入图片描述

检查函数是查看是否能形成足够多的连续堆数。数到足够连续数,花束+1,然后枝数归0。
在这里插入图片描述时间复杂:
O(NlogC)
空间:
O(1)

小张的刷题计划

类似分割数组最大值。
左区间为0,都是小杨做题,右区间为数组和
在这里插入图片描述不同的在于check函数,我们有个机会减去最大值。
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值