二分搜索每一步将搜索空间减半。在 n 个元素的排序数组上,它在 O(log n) 时间内找到目标。
def binary_search(nums, target):
lo, hi = 0, len(nums) - 1
while lo <= hi:
mid = (lo + hi) // 2
if nums[mid] == target:
return mid
elif nums[mid] < target:
lo = mid + 1
else:
hi = mid - 1
return -1
简单 - 但二分搜索的真正威力远远超出了排序数组。
只要您在某个范围内有单调条件,二分搜索就会起作用。 “数组”甚至不需要存在 - 你只需要一个范围 [lo, hi] 和一个在某个边界从 False 翻转到 True (反之亦然)的函数。
Search space: [lo .................. hi]
Condition: F F F F T T T T
^-- answer
二分搜索首次发布于 1946 年,但第一个无错误版本直到 1962 年才编写 - 16 年的差一错误!
不要搜索数组,而是搜索答案空间。问:“我能达到结果 X 吗?”如果是,请尝试较小的;如果没有,请尝试更大的。
Koko 有 n 堆香蕉和 h 小时。找到最小进食速度,以便她及时吃完。
def min_speed(piles, h):
lo, hi = 1, max(piles)
while lo < hi:
mid = (lo + hi) // 2
hours = sum((p + mid - 1) // mid for p in piles)
if hours <= h:
hi = mid # speed works, try slower
else:
lo = mid + 1 # too slow, go faster
return lo
答案空间是 [1, max(piles)] 并且条件是单调的 - 更高的速度总是意味着更少的时间。
已排序的数组在某个枢轴处旋转:[4, 5, 6, 7, 0, 1, 2]。一半总是排序的。比较 mid 和 lo 来决定哪一半,然后检查目标是否属于已排序的一半。
[4, 5, 6, 7, 0, 1, 2]
L M R
Left half [4..7] is sorted.
Target 1 not in [4..7] → search right.
登录 参与讨论
在旋转排序数组 [3,4,5,1,2] 中,当 mid=2(值 5)时哪一半已排序?
要找到第一个出现,当您击中目标时,不要停止 - 设置 hi = mid 并继续向左搜索。对于最后,设置 lo = mid + 1 并向右搜索。
这对搜索还为您提供了目标的计数:last - first + 1。
比两个邻居都大的元素。即使在未排序的数组中,二分搜索也有效:如果 nums[mid] < nums[mid + 1],则峰值在右侧;如果 nums[mid] < nums[mid + 1],则峰值在右侧;否则它在左边。 O(log n)。
为什么即使数组未排序,峰值查找仍可与二分搜索一起使用?什么属性取代了这里的排序顺序?
如果行已排序并且每行的第一个元素大于前一行的最后一个,则将矩阵视为 m × n 元素的单个排序数组。将索引 k 映射到行 k // n、列 k % n。
找到最大的整数 x 其中 x * x ≤ n。搜索空间:[0, n]。经典的二分搜索答案。
def sqrt(n):
lo, hi = 0, n
while lo <= hi:
mid = (lo + hi) // 2
if mid * mid <= n:
lo = mid + 1
else:
hi = mid - 1
return hi
诸如“拆分数组最大总和”或“D 天内运送包裹的能力”之类的问题要求您最小化最坏的情况。答案是单调的:如果容量 C 有效,那么 C+1 也有效。对 C 进行二分查找
对于”D 天内运送包裹的能力”,二分搜索的搜索空间是多少?
lo, hi = min_possible, max_possible
while lo < hi:
mid = (lo + hi) // 2
if condition(mid):
hi = mid # mid works, try smaller
else:
lo = mid + 1 # mid fails, need larger
return lo
根据您是否寻求第一个 True 或 最后一个 True 来调整 hi = mid 与 lo = mid。
在大小为 S 的答案空间上进行 O(n) 可行性检查的二分搜索的时间复杂度是多少?
当您在问题陈述中看到短语“最小可能的最大值”或“最大可能的最小值”时,您应该立即想到什么?