二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构
代码实现
def binary_search(arr: list, target: int) -> int:"""非递归版本"""# 数据的范围l, r = 0, len(arr) - 1while l <= r:# mid = (l+r) // 2 会存在越界mid = l + (r - l) // 2if arr[mid] == target:return midif target > arr[mid]:# 需要查找的数据在右边数组中l = mid + 1else:# 需要查找的数据在左边的数组中r = mid - 1return -1def binary_search(arr: list, target: int, l: int, r: int) -> int:"""递归版本"""# 数据的范围if l > r:return -1mid = l + (r - l) // 2if arr[mid] == target:return midif target > arr[mid]:# 需要查找的数据在右边数组中l = mid + 1else:# 需要查找的数据在左边的数组中r = mid - 1return binary_search(arr=arr, target=target, l=l, r=r)
二分查找变种
class BinarySearch:@staticmethoddef binary_search(arr: list, target: int) -> int:"""二分查找非递归版本"""# 数据的范围l, r = 0, len(arr) - 1while l <= r:# mid = (l+r) // 2 会存在越界mid = l + (r - l) // 2if arr[mid] == target:return midif target > arr[mid]:# 需要查找的数据在右边数组中l = mid + 1else:# 需要查找的数据在左边的数组中r = mid - 1return -1def binary_search_r(self, arr: list, target: int, l: int, r: int) -> int:"""二分查找递归版本"""# 数据的范围if l > r:return -1mid = l + (r - l) // 2if arr[mid] == target:return midif target > arr[mid]:# 需要查找的数据在右边数组中l = mid + 1else:# 需要查找的数据在左边的数组中r = mid - 1return self.binary_search_r(arr=arr, target=target, l=l, r=r)@staticmethoddef binary_upper(data: list, target: int) -> int:# 寻找大于 target的最小值的下标l, r = 0, len(data)while l < r:mid = l + (r - l) // 2if data[mid] <= target:l = mid + 1else:# 可能当前mid表示的值就是大于target 且是最小值r = midreturn l@staticmethoddef binary_lower(data: list, target: int) -> int:""" 寻找小于 target值的最大值下标 """# 在 [l,r] 中找解l, r = -1, len(data) -1while l < r:mid = l + (r - l +1) // 2if data[mid] < target:l = midelse:r = mid -1return ldef binary_ceil(self, data: list, target: int) -> int:"""天花板找到原始数据中值为target的最大索引如果没有返回>target的最小值索引"""u = self.binary_upper(data, target)if data[u - 1] == target and u - 1 >= 0:return u - 1return u
时间复杂度
O(logn)
