- Python
Python 二分查找教程
- 2025-4-5 8:46:22 @
Python 二分查找教程(0基础,通俗易懂)
1. 什么是二分查找?
二分查找是一种高效的查找算法,用于在有序数组中查找目标值。它的核心思想是通过不断缩小查找范围,快速定位目标值的位置。
- 特点:
- 只能用于有序数组。
- 时间复杂度为 O(log n),比线性查找(O(n))快得多。
2. 二分查找的基本原理
假设你有一本字典,要查一个单词,你会从中间打开字典:
- 如果中间的单词正好是你想找的,就找到了!
- 如果目标单词在中间单词之前,就只看前半部分。
- 如果目标单词在中间单词之后,就只看后半部分。
- 重复以上步骤,直到找到目标单词或确定它不存在。
3. 二分查找的实现步骤
我们用一个例子来说明:在有序数组 [1, 3, 5, 7, 9, 11]
中查找数字 7
。
步骤:
- 找到数组的中间位置,计算中间索引:
mid = (left + right) // 2
初始时,left = 0
,right = len(array) - 1
。 - 比较中间值与目标值:
- 如果中间值等于目标值,返回索引。
- 如果目标值小于中间值,继续在左半部分查找(更新
right = mid - 1
)。 - 如果目标值大于中间值,继续在右半部分查找(更新
left = mid + 1
)。
- 重复上述过程,直到找到目标值或查找范围为空。
4. Python代码实现
以下是二分查找的完整代码实现:
def binary_search(arr, target):
# 定义左右边界
left, right = 0, len(arr) - 1
while left <= right:
# 计算中间索引
mid = (left + right) // 2
# 检查中间值是否为目标值
if arr[mid] == target:
return mid # 找到目标值,返回索引
elif arr[mid] < target:
left = mid + 1 # 目标值在右半部分
else:
right = mid - 1 # 目标值在左半部分
# 如果循环结束仍未找到,返回 -1 表示未找到
return -1
# 测试代码
arr = [1, 3, 5, 7, 9, 11]
target = 7
result = binary_search(arr, target)
print(f"目标值 {target} 的索引是: {result}")
运行结果:
目标值 7 的索引是: 3
5. 二分查找的关键点
- 数组必须有序:如果数组无序,先对数组进行排序(例如使用
sorted()
或.sort()
方法)。 - 查找范围的更新:每次比较后,更新
left
或right
,确保范围不断缩小。 - 终止条件:当
left > right
时,表示查找范围为空,结束查找。
6. 二分查找的应用场景
- 在有序数据中快速查找某个值的位置。
- 查找某个值是否存在(返回布尔值)。
- 查找第一个大于或等于目标值的位置(变体问题)。
7. 二分查找的变体问题
有时我们需要解决一些特殊的二分查找问题,比如:
-
查找第一个大于等于目标值的位置:
def find_first_greater_or_equal(arr, target): left, right = 0, len(arr) - 1 while left <= right: mid = (left + right) // 2 if arr[mid] >= target: right = mid - 1 # 继续向左查找更小的满足条件的值 else: left = mid + 1 return left # 返回第一个大于等于目标值的位置
-
查找最后一个小于等于目标值的位置:
def find_last_less_or_equal(arr, target): left, right = 0, len(arr) - 1 while left <= right: mid = (left + right) // 2 if arr[mid] <= target: left = mid + 1 # 继续向右查找更大的满足条件的值 else: right = mid - 1 return right # 返回最后一个小于等于目标值的位置
8. 常见错误与注意事项
- 数组是否有序:二分查找的前提是数组必须有序,否则结果不正确。
- 边界条件:注意
left
和right
的更新,避免死循环。 - 整数溢出:在某些语言中(如C++),
(left + right) // 2
可能导致溢出,建议使用left + (right - left) // 2
。
9. 小练习
- 给定一个有序数组
[2, 4, 6, 8, 10, 12]
,使用二分查找找出数字8
的索引。 - 修改二分查找代码,使其返回目标值是否存在(返回布尔值)。
- 实现一个函数,找到数组中第一个大于等于目标值的位置。
总结
二分查找是一种简单但非常高效的查找算法,适合处理有序数组。只要记住以下几点,就能轻松掌握:
- 有序数组是前提。
- 不断缩小范围是关键。
- 更新边界条件要准确。
希望这篇教程对你有帮助!如果有任何疑问,请随时提问! 😊
5 条评论
-
admin SU @ 2025-4-9 19:08:19
-
2025-4-9 19:02:56@
二分查找每次把查找区间缩小一半,在最坏情况下,查找次数满足公式 ( 是查找次数, 是数据规模, 表示向上取整 ) 。以下是不同数据规模下10次二分查找的情况分析:
- 100次:因为 ,向上取整为7次 ,10次二分查找远超过查找100个数据所需次数。
- 1000次 : ,向上取整为10次 ,10次二分查找最多可查找约1000个数据,刚好满足。
- 10万次 : ,向上取整为17次 ,10次二分查找不能满足查找10万个数据的需求。
- 100万次 : ,向上取整为20次 ,10次二分查找远不能满足查找100万个数据的需求 。
- 1000万次 : ,向上取整为24次 ,10次二分查找远不能满足查找1000万个数据的需求 。
- 1亿次 : ,向上取整为27次 ,10次二分查找远不能满足查找1亿个数据的需求 。
所以10次二分查找最多能处理约1000个数据规模,仅在1000次这个量级符合要求,其他量级(100次远不需要10次查找,10万、100万、1000万、1亿次则超出了10次查找能处理的范围 )不符合。
-
2025-4-5 10:06:24@
Python 递归版本的二分查找教程(0基础,通俗易懂)
1. 什么是递归版本的二分查找?
递归版本的二分查找是基于函数调用自身来实现的二分查找算法。它和普通版本的二分查找逻辑相同,但通过递归的方式来不断缩小查找范围。
- 优点:
- 代码简洁直观。
- 符合二分查找的“分治”思想。
- 缺点:
- 可能会占用更多的栈空间(对于非常大的数组,可能导致栈溢出)。
2. 递归的基本思想
递归的核心思想是将大问题分解成小问题,直到问题变得足够简单可以直接解决。对于二分查找来说:
- 找到数组的中间值。
- 如果目标值等于中间值,直接返回索引。
- 如果目标值小于中间值,在左半部分继续查找。
- 如果目标值大于中间值,在右半部分继续查找。
- 重复上述过程,直到找到目标值或查找范围为空。
3. 递归版本的二分查找步骤
我们用一个例子来说明:在有序数组
[1, 3, 5, 7, 9, 11]
中查找数字7
。步骤:
- 定义递归函数,传入数组、目标值、当前的左右边界。
- 计算中间索引:
mid = (left + right) // 2
- 比较中间值与目标值:
- 如果中间值等于目标值,返回索引。
- 如果目标值小于中间值,递归调用函数,查找左半部分(更新
right = mid - 1
)。 - 如果目标值大于中间值,递归调用函数,查找右半部分(更新
left = mid + 1
)。
- 如果
left > right
,表示查找范围为空,返回-1
表示未找到。
4. Python代码实现
以下是递归版本的二分查找完整代码:
def binary_search_recursive(arr, target, left, right): # 基本条件:如果查找范围为空,返回 -1 if left > right: return -1 # 计算中间索引 mid = (left + right) // 2 # 检查中间值是否为目标值 if arr[mid] == target: return mid # 找到目标值,返回索引 elif arr[mid] < target: # 目标值在右半部分,递归查找右半部分 return binary_search_recursive(arr, target, mid + 1, right) else: # 目标值在左半部分,递归查找左半部分 return binary_search_recursive(arr, target, left, mid - 1) # 测试代码 arr = [1, 3, 5, 7, 9, 11] target = 7 result = binary_search_recursive(arr, target, 0, len(arr) - 1) print(f"目标值 {target} 的索引是: {result}")
运行结果:
目标值 7 的索引是: 3
5. 代码解析
- 递归终止条件:
- 当
left > right
时,表示查找范围为空,直接返回-1
。
- 当
- 递归调用:
- 根据中间值与目标值的比较结果,递归调用函数,更新查找范围。
- 返回值:
- 如果找到目标值,返回其索引。
- 如果未找到,返回
-1
。
6. 递归版本的关键点
- 递归终止条件:必须明确什么时候停止递归(即
left > right
)。 - 参数传递:每次递归调用时,需要正确传递新的
left
和right
边界。 - 避免栈溢出:递归深度受限于系统栈大小,因此不适用于非常大的数组。
7. 递归版本的应用场景
- 查找某个值是否存在。
- 查找某个值的位置(返回索引)。
- 解决一些变体问题(如第一个大于等于目标值的位置)。
8. 小练习
- 给定一个有序数组
[2, 4, 6, 8, 10, 12]
,使用递归版本的二分查找找出数字8
的索引。 - 修改递归版本的代码,使其返回目标值是否存在(返回布尔值)。
- 实现一个递归版本的函数,找到数组中第一个大于等于目标值的位置。
9. 总结
递归版本的二分查找虽然代码更简洁,但也需要注意以下几点:
- 递归终止条件是关键,否则会导致无限递归。
- 数组必须有序,否则结果不正确。
- 对于非常大的数组,建议使用非递归版本以避免栈溢出。
希望这篇教程对你有帮助!如果有任何疑问,请随时提问! 😊
- 优点:
-
2025-4-5 9:17:37@
Python 递归版本的二分查找教程。
一、递归的概念
在开始讲解递归版本的二分查找之前,我们先来了解一下什么是递归。递归就是在函数的定义中调用函数自身的方法。一个递归函数通常包含两个部分:
- 基线条件:也叫终止条件,是递归结束的条件,防止函数无限调用自身导致栈溢出错误。
- 递归条件:函数调用自身的部分,每次调用会使问题规模逐渐减小,最终达到基线条件。
二、二分查找的基本思路回顾
二分查找是一种在有序数组中查找特定元素的高效算法。它的基本思路是将有序数组分成两部分,通过比较中间元素和目标元素的大小关系,来决定继续在数组的左半部分还是右半部分查找,不断缩小查找范围,直到找到目标元素或者确定目标元素不存在。
三、递归版本二分查找的实现步骤
- 基线条件:当左边界大于右边界时,说明目标元素不在数组中,此时返回 -1。
- 递归条件:
- 计算中间位置
mid
。 - 如果中间元素等于目标元素,返回中间位置
mid
。 - 如果中间元素大于目标元素,递归调用函数在左半部分查找。
- 如果中间元素小于目标元素,递归调用函数在右半部分查找。
- 计算中间位置
四、Python 代码示例
def binary_search_recursive(arr, target, left, right): # 基线条件:左边界大于右边界,说明目标元素不存在 if left > right: return -1 # 计算中间位置 mid = (left + right) // 2 # 如果中间元素等于目标元素,返回中间位置 if arr[mid] == target: return mid # 如果中间元素大于目标元素,在左半部分继续查找 elif arr[mid] > target: return binary_search_recursive(arr, target, left, mid - 1) # 如果中间元素小于目标元素,在右半部分继续查找 else: return binary_search_recursive(arr, target, mid + 1, right) # 示例用法 arr = [1, 3, 5, 7, 9, 11, 13] target = 7 result = binary_search_recursive(arr, target, 0, len(arr) - 1) if result != -1: print(f"目标元素 {target} 在数组中的索引是 {result}") else: print(f"目标元素 {target} 不在数组中")
五、代码解释
- 函数
binary_search_recursive
接收四个参数:arr
是要查找的有序数组,target
是目标元素,left
是当前查找范围的左边界,right
是当前查找范围的右边界。 - 首先判断基线条件
if left > right:
,如果左边界大于右边界,说明目标元素不在当前查找范围内,返回 -1。 - 计算中间位置
mid = (left + right) // 2
。 - 然后比较中间元素和目标元素:
- 如果
arr[mid] == target
,表示找到了目标元素,返回mid
。 - 如果
arr[mid] > target
,说明目标元素在左半部分,递归调用binary_search_recursive(arr, target, left, mid - 1)
。 - 如果
arr[mid] < target
,说明目标元素在右半部分,递归调用binary_search_recursive(arr, target, mid + 1, right)
。
- 如果
- 最后通过示例用法展示了如何调用这个递归函数进行二分查找,并根据返回结果输出相应的信息。
希望这个教程能让你理解 Python 递归版本的二分查找,通过不断练习,你可以更好地掌握递归和二分查找的应用。
-
2025-4-5 8:48:05@
二分查找概述
二分查找(Binary Search)也被叫做折半查找,它是一种在有序数组里高效查找特定元素的算法。其核心思想是不断把搜索区间一分为二,依据中间元素和目标元素的大小关系,排除掉一半的搜索区间,进而逐步缩小搜索范围,直至找到目标元素或者确定目标元素不存在。
适用条件
二分查找只能用于有序数组,即数组里的元素按照升序或者降序排列。
算法步骤
- 初始化:设定左右边界,左边界
left
指向数组首个元素,右边界right
指向数组末尾元素。 - 计算中间位置:算出中间位置
mid
,公式为mid = (left + right) // 2
(在 Python 里使用//
进行整除操作)。 - 比较中间元素和目标元素:
- 若中间元素等于目标元素,就找到了目标元素,返回中间位置
mid
。 - 若中间元素大于目标元素,说明目标元素在左半部分,更新右边界
right = mid - 1
。 - 若中间元素小于目标元素,说明目标元素在右半部分,更新左边界
left = mid + 1
。
- 若中间元素等于目标元素,就找到了目标元素,返回中间位置
- 重复步骤 2 和 3:只要左边界小于等于右边界,就持续执行上述操作。
- 未找到目标元素:若左边界大于右边界,表明目标元素不在数组中,返回 -1。
Python 代码实现
def binary_search(arr, target): # 初始化左边界 left = 0 # 初始化右边界 right = len(arr) - 1 while left <= right: # 计算中间位置 mid = (left + right) // 2 if arr[mid] == target: # 找到目标元素,返回中间位置 return mid elif arr[mid] > target: # 中间元素大于目标元素,更新右边界 right = mid - 1 else: # 中间元素小于目标元素,更新左边界 left = mid + 1 # 未找到目标元素,返回 -1 return -1 # 示例用法 arr = [1, 3, 5, 7, 9, 11, 13] target = 7 result = binary_search(arr, target) if result != -1: print(f"目标元素 {target} 在数组中的索引是 {result}") else: print(f"目标元素 {target} 不在数组中")
复杂度分析
- 时间复杂度:每次迭代都会把搜索区间缩小一半,所以时间复杂度是 ,这里的 是数组的长度。
- 空间复杂度:只使用了常数级别的额外空间,空间复杂度为 。
注意事项
- 二分查找仅适用于有序数组,若数组无序,需先对其排序。
- 在计算中间位置时,为避免整数溢出,可采用
mid = left + (right - left) // 2
替代mid = (left + right) // 2
。
通过上述教程,你应该对二分查找算法有了基本的认识,并且能够使用 Python 实现简单的二分查找功能。
- 初始化:设定左右边界,左边界
- 1