折半查找的核心逻辑是基于“数组有序”的前提,通过不断将查找区间缩小一半来高效定位目标值

折半查找的核心逻辑是基于“数组有序”的前提,通过不断将查找区间缩小一半来高效定位目标值。其基本步骤如下:

  1. 定义查找范围的边界 lowhigh,初始为数组首尾下标。
  2. 在每一步中计算中间位置 mid = low + (high - low) // 2(避免整数溢出)。
  3. 比较目标值 key 与中间元素 arr[mid]
    • key == arr[mid],查找成功,返回 mid
    • key < arr[mid],说明目标在左半区,更新 high = mid - 1
    • key > arr[mid],说明目标在右半区,更新 low = mid + 1
  4. 重复上述过程,直到 low > high 时结束循环,表示未找到,返回 -1

两种实现方式

(1)迭代版(Bsearch)
def bsearch(arr, key):
    low, high = 0, len(arr) - 1
    while low <= high:
        mid = low + (high - low) // 2
        if arr[mid] == key:
            return mid
        elif key < arr[mid]:
            high = mid - 1
        else:
            low = mid + 1
    return -1
  • 使用循环控制流程,空间复杂度为 O(1)
  • 更适合大规模数据或对栈空间敏感的环境。
(2)递归版(Bsearch_rec)
def bsearch_rec(arr, key, low, high):
    if low > high:
        return -1
    mid = low + (high - low) // 2
    if arr[mid] == key:
        return mid
    elif key < arr[mid]:
        return bsearch_rec(arr, key, low, mid - 1)
    else:
        return bsearch_rec(arr, key, mid + 1, high)
  • 利用函数调用自身实现分治,代码更简洁易懂。
  • 空间复杂度为 O(log n),因递归深度约为 log₂n。

折半查找的特点总结

特性描述
前提条件数组必须有序且支持随机访问
时间复杂度O(log n) —— 显著优于顺序查找的 O(n)
空间复杂度迭代:O(1),递归:O(log n)
适用结构数组等连续存储结构;不适用于链表
动态操作不适合频繁插入/删除的场景(维护有序成本高)

折半查找要求数据必须是有序的,是因为其核心逻辑依赖于通过比较中间元素来判断目标值位于左半部分还是右半部分。这种“决策依据”只有在数据有序的前提下才成立。

详细解释:

假设我们有一个数组 arr 和一个目标值 key,折半查找每次都会取中间元素 arr[mid] 进行比较:

  • 如果 key == arr[mid],查找成功;
  • 如果 key < arr[mid],则认为 key 应该出现在 mid 左侧 —— 但这仅在数组有序时才正确
  • 如果 key > arr[mid],则认为 key 应该出现在 mid 右侧 —— 同样依赖于顺序排列。
举个例子:

无序数组:[5, 2, 9, 1, 7],我们要找 key = 3
中间元素是 9,由于 3 < 9,算法会去左边 [5, 2] 查找,但实际上 3 并不在数组中,即使存在也可能被错误地“跳过”。

而如果是有序数组:[1, 2, 5, 7, 9],中间是 53 < 5 → 正确进入左半部分 [1, 2],继续查找可得结果或确认不存在。

✅ 所以:只有当数组有序时,“小于中间值就一定在左边,大于就在右边”这一推理才成立,否则查找过程将失去正确性。


此外,有序性还保证了以下几点:

  • 每次都能安全地排除一半的数据,确保时间复杂度为 O(log n);
  • 不会出现遗漏或误判的情况。

类比理解:

就像查字典时,你是按字母顺序翻页的。如果字典的单词被打乱了,你就无法通过“当前词太大”来决定往前翻还是往后翻。


在这里插入图片描述

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bol5261

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值