二分法查找,也称为折半法,是一种在有序数组中查找特定元素的搜索算法。 二分法查找的思路如下:
(1)首先,从数组的中间元素开始搜索,如果该元素正好是目标元素,则搜索过程结束,否则执行下一步。
(2)如果目标元素大于/小于中间元素,则在数组大于/小于中间元素的那一半区域查找,然后重复步骤的操作。
(3)如果某一步数组为空,则表示找不到目标元素。
以下是二分法常用的模板,包括查找指定数、查找左边界和右边界。
1. 查找指定数
查找指定数是指只需要查找出指定数在数组中的索引即可,并不规定指定数在数组中所处的相对位置。
def binary_Search(nums, target):
left, right = 0, len(nums)-1 # 搜索区间两边为闭
while left <= right: # 注意停止条件,停止条件为[left, left+1]
mid = (right + left) // 2
# 找到指定数并返回其索引
if nums[mid] == target:
return mid
elif nums[mid] < target:
left = mid + 1 # 因为mid已经搜索过
else:
right = mid - 1
return -1
此处要注意的是:
- while循环的条件
left <= right
代表中止条件为[left, left+1]
。如果不加等号,则中止条件为[left,left]
此时life
并没有被搜索,是不正确的。
2. 左边界查找
左边界查找是指需要查找出指定数在数组中第一次出现的位置的索引。
def left_Search(nums, target):
left, right = 0, len(nums)-1 # 搜索区间两边为闭
while left <= right:
mid = (right + left) // 2
if nums[mid] < target:
left = mid + 1
else:
right = mid - 1
if left >= len(nums) or nums[left] != target:
return -1
return left
此处要注意的是:
- 主要是要理解左边界查找和查找指定数的区别,在查找指定数时
nums[mid] == target
表示已经找到指定数,则返回该数索引即为结果。而在左边界查找时nums[mid] == target
并不能表示已经得到结果,因为我们不知道这个数是不是最左边的,所以当nums[mid] == target
时我们要将右边界设置为mid - 1
,再次进行循环。
3. 右边界查找
右边界查找跟左边界类似,只不过右边界需要的是查找出最后一次出现的位置的索引。
def left_Search(nums, target):
left, right = 0, len(nums)-1 # 搜索区间两边为闭
while left <= right:
mid = (right + left) // 2
if nums[mid] <= target:
left = mid + 1
else:
right = mid - 1
if right < 0 or nums[right] != target:
return -1
return right
此处要注意的是:
- 主要是要理解右边界查找和左边界查找的区别,在左边界查找时
nums[mid] == target
我们要去查找左边的区间是否有指定数,所以当nums[mid] == target
时我们要将右边界设置为mid - 1
,再次进行循环。而在右查找时我们要去查找右边的区间是否有指定数,所以当nums[mid] == target
时我们要将左边界设置为mid - 1
以上就是二分法查找的三种模板,基本上所有有关二分法的案例都可以使用。不过本篇文章只是介绍了利用循环去完成的方法,还可以用递归去实现,这里就不一一举例,有兴趣的同学可以自己去尝试一下。