二分查找问题主要分为三类最常用场景:1)元素查找。2)左边界查找。3)右边界查找。
不同场景下的核心点在于查找循环跳出条件,以及左右指针更新公式。
具体可以参考二分搜索详解
704. 二分查找
解法:二分查找(元素搜索)
分为搜索区间左闭右开和闭区间两种情况。可以根据代码体会两者的不同。
class Solution:
def search(self, nums: List[int], target: int) -> int:
# 左闭右开
left, right = 0, len(nums)
while left < right:
mid = left + (right - left) // 2
if nums[mid] == target:
return mid
elif nums[mid] > target:
right = mid
elif nums[mid] < target:
left = mid + 1
return -1
class Solution:
def search(self, nums: List[int], target: int) -> int:
# 闭区间
left, right = 0, len(nums) - 1
while left <= right:
mid = left + (right - left) // 2
if nums[mid] == target:
return mid
elif nums[mid] > target:
right = mid - 1
elif nums[mid] < target:
left = mid + 1
return -1
34. 在排序数组中查找元素的第一个和最后一个位置
解法:二分查找(边界搜索)
同样也分为左闭右开和闭区间两种情况。
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
if not nums:
return [-1, -1]
res = list()
#计算左边界,左闭右开
l, r = 0, len(nums)
while l < r:
mid = (l + r) // 2
if nums[mid] >= target:
r = mid
else:
l = mid + 1
#不存在,直接返回
if l == len(nums) or nums[l] != target:
return [-1, -1]
res.append(l)
#计算右边界,闭区间
l, r = 0, len(nums) - 1
while l <= r:
mid = (l + r + 1) // 2
if nums[mid] <= target:
l = mid + 1
else:
r = mid - 1
# target在数组一定存在,因此不用进行重复判断
res.append(r)
return res