Binary Search
闭区间写法
找该数
|
|
找左边界
|
|
左闭右开
找左边界
|
|
如果 target 不存在,搜索左侧边界的二分搜索返回的索引是大于 target 的最小索引。
<, <=, >, >=
“>=“即为寻找某数的左侧边界
“>“可看作寻找x+1的左侧边界
“<=“看做寻找x+1的左侧边界-1
“<“看做寻找x的左侧边界-1
非单调数组
红色(l-1及其左边)代表目标左边,蓝色(r及其右边)代表目标及其右边,也就是说nums[n-1]初始为蓝色。
162. 寻找峰值
每次拿nums[mid]和 nums[mid+1]比较。以左闭右开写法举例:
- nums[mid]<nums[mid+1]: 峰值在mid+1及其右侧, 因此l=mid+1
- nums[mid]>nums[mid+1]: 峰值为mid及其左侧区域, r=mid
注意这题需要初始 r=len(nums)-1,不然 nums[mid+1]会溢出。但即使如此,num[n-1]也不会在答案中被漏掉,这是因为循环结束时,l==r, 会返回。如[1,2,3,4].
左闭右开写法: r及其右边可能是答案,l-1及其左边不是答案
1901. 寻找峰值 II
要求时间复杂度为O(NlogM),因此只需要对行进行二分。
先找行,nums[mid]这行里面最大的元素X,拿它和它下面的元素A比较。
如果小于,则从A出发,一定存在一条单调递增直到峰值的路径,并且不会走到mid那一行,因为 mid那一行最大的都比A小了。
所以就在下面那几排找峰值即可。
如果大于,要么X就是峰顶,要么X往上走,存在一条走到峰顶的路
153. 寻找旋转排序数组中的最小值
将nums[mid]与nums[n-1]比较。
单调数组
4. 寻找两个正序数组的中位
可视为划分数组,在两个数组中找出一条分割线,分割线左边的元素个数为(m+n+1)/2,分割线左边最大的数<分割线右边最小的数
如果总共有奇数个元素,那么答案为分割线左边最大的数
如果总共有偶数个元素,那么答案为分割线左边最大的数与分割线右边最小的数的平均值。
把第一个数组的每个数字间隙视为可枚举的对象,二分搜索合适的间隙。总共有m+1个间隙。
为了防止索引越界,令长度短的数组为第一个数组。
目标分割线满足:nums1[i-1]<nums2[j] and nums1[i]>nums2[j-1],j=(m+n+1)//2-i
类似题目:295. 数据流的中位数
用堆实现,分左边堆和右边堆。左边堆的数量可以比右边多一个。
最小化最大值
410. 分割数组的最大值.
遍历数组,当前累加和大于mid时,创建一个新的分割,cnt+=1.
当 cnt==k时,返回 False。
K 小/大
第 k 小等价于:求最小的 x,满足 ≤x 的数至少有 k 个。
719. 找出第 K 小的数对距离
辅助函数:数一下所有距离中,小于等于X的距离个数。对应滑动窗口的“越短越合法”。