二分法查找,也稱為折半法,是一種在有序數組中查找特定元素的搜索算法。 二分法查找的思路如下:
(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
以上就是二分法查找的三種模板,基本上所有有關二分法的案例都可以使用。不過本篇文章只是介紹了利用循環去完成的方法,還可以用遞歸去實現,這里就不一一舉例,有興趣的同學可以自己去嘗試一下。