本文目录导读:

我来给你介绍Python二分查找的精准实现方法,包括基础版本和多种实用案例。
基础二分查找(精准查找)
标准实现
def binary_search(arr, target):
"""
精准二分查找,返回目标值的索引
如果不存在,返回-1
"""
left, right = 0, len(arr) - 1
while left <= right:
mid = left + (right - left) // 2 # 防止整数溢出
if arr[mid] == target:
return mid
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return -1 # 未找到
# 测试
arr = [1, 3, 5, 7, 9, 11, 13, 15]
print(binary_search(arr, 7)) # 输出: 3
print(binary_search(arr, 8)) # 输出: -1
查找边界值(精准定位)
查找第一个等于target的位置
def find_first_equal(arr, target):
"""查找第一个等于target的元素索引"""
left, right = 0, len(arr) - 1
result = -1
while left <= right:
mid = left + (right - left) // 2
if arr[mid] == target:
result = mid # 记录当前位置
right = mid - 1 # 继续向左查找
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return result
# 测试
arr = [1, 2, 2, 2, 3, 4, 5]
print(find_first_equal(arr, 2)) # 输出: 1
查找最后一个等于target的位置
def find_last_equal(arr, target):
"""查找最后一个等于target的元素索引"""
left, right = 0, len(arr) - 1
result = -1
while left <= right:
mid = left + (right - left) // 2
if arr[mid] == target:
result = mid # 记录当前位置
left = mid + 1 # 继续向右查找
elif arr[mid] < target:
left = mid + 1
else:
right = mid - 1
return result
# 测试
arr = [1, 2, 2, 2, 3, 4, 5]
print(find_last_equal(arr, 2)) # 输出: 3
查找近似值(最接近目标)
查找最接近target的元素
def find_closest(arr, target):
"""查找最接近target的元素索引"""
if not arr:
return -1
left, right = 0, len(arr) - 1
# 边界情况处理
if target <= arr[left]:
return left
if target >= arr[right]:
return right
while left < right:
mid = left + (right - left) // 2
if arr[mid] == target:
return mid
if arr[mid] < target:
left = mid + 1
else:
right = mid - 1
# 比较两个最接近的元素
if abs(arr[left] - target) <= abs(arr[left + 1] - target):
return left
else:
return left + 1
# 测试
arr = [1, 3, 5, 7, 9, 11]
print(find_closest(arr, 6)) # 输出: 2 (值5)
print(find_closest(arr, 8)) # 输出: 3 (值7)
实际应用案例
案例1:查找插入位置
def search_insert(nums, target):
"""
LeetCode 35: 搜索插入位置
返回target应该插入的索引位置
"""
left, right = 0, len(nums) - 1
while left <= right:
mid = left + (right - left) // 2
if nums[mid] == target:
return mid
elif nums[mid] < target:
left = mid + 1
else:
right = mid - 1
return left
# 测试
nums = [1, 3, 5, 6]
print(search_insert(nums, 5)) # 输出: 2
print(search_insert(nums, 2)) # 输出: 1
print(search_insert(nums, 7)) # 输出: 4
案例2:旋转数组查找
def search_rotated(nums, target):
"""
LeetCode 33: 搜索旋转排序数组
"""
if not nums:
return -1
left, right = 0, len(nums) - 1
while left <= right:
mid = left + (right - left) // 2
if nums[mid] == target:
return mid
# 判断哪部分是有序的
if nums[left] <= nums[mid]: # 左半部分有序
if nums[left] <= target < nums[mid]:
right = mid - 1
else:
left = mid + 1
else: # 右半部分有序
if nums[mid] < target <= nums[right]:
left = mid + 1
else:
right = mid - 1
return -1
# 测试
nums = [4, 5, 6, 7, 0, 1, 2]
print(search_rotated(nums, 0)) # 输出: 4
print(search_rotated(nums, 3)) # 输出: -1
案例3:求平方根
def my_sqrt(x):
"""
LeetCode 69: x的平方根
返回整数部分
"""
if x == 0 or x == 1:
return x
left, right = 1, x
while left <= right:
mid = left + (right - left) // 2
if mid * mid == x:
return mid
elif mid * mid < x:
left = mid + 1
else:
right = mid - 1
return right
# 测试
print(my_sqrt(8)) # 输出: 2
print(my_sqrt(16)) # 输出: 4
性能优化版本
使用bisect模块(Python内置)
import bisect
# bisect_left: 查找第一个大于等于target的位置
# bisect_right: 查找第一个大于target的位置
arr = [1, 2, 2, 2, 3, 4, 5]
# 查找等于target的范围
left_idx = bisect.bisect_left(arr, 2) # 第一个2的位置
right_idx = bisect.bisect_right(arr, 2) # 最后一个2的下一个位置
print(f"2的范围: [{left_idx}, {right_idx-1}]") # 输出: [1, 3]
通用二分查找模板
def binary_search_template(nums, target):
"""
通用二分查找模板
"""
left, right = 0, len(nums) - 1
while left + 1 < right: # 当区间长度>2时
mid = left + (right - left) // 2
if nums[mid] == target:
return mid
elif nums[mid] < target:
left = mid
else:
right = mid
# 最后检查两个元素
if nums[left] == target:
return left
if nums[right] == target:
return right
return -1
# 测试
arr = [1, 3, 5, 7, 9, 11, 13, 15]
print(binary_search_template(arr, 7)) # 输出: 3
注意事项
- 边界条件:确保left <= right正确使用
- 中点计算:使用
left + (right - left) // 2避免整数溢出 - 循环终止:确保最终能退出循环
- 数组有序:二分查找要求数组有序
- 重复元素:注意处理重复元素的情况
这些案例覆盖了大多数二分查找的应用场景,可以根据具体需求选择合适的实现方式。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播