二分查找使用记录(使用low + (high - low) / 2的原因)

本文详细分析了在实现二分查找算法时遇到的整数溢出问题,特别是在计算中间值mid时。通过举例说明,当low和high之和超过int类型的最大值时,会导致溢出,从而引发超时异常。解决方法是使用low + (high - low) / 2来避免这种溢出情况,确保算法能够正确运行。此外,文章还探讨了防止溢出的原理和代码修正后的正确实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二分查找使用记录(使用low + (high - low) / 2的原因)

记录一下二分查找中遇到的问题,来源于一道简单的力扣题

题目

https://leetcode-cn.com/problems/first-bad-version/

在这里插入图片描述

/* The isBadVersion API is defined in the parent class VersionControl.
      bool IsBadVersion(int version); */
public class Solution : VersionControl {
    public int FirstBadVersion(int n) {
        int low = 1;
        int high = n;
        while(low < high){
            int mid = (low + high) / 2;
            if (IsBadVersion(mid))  high = mid;
            else low = mid + 1;
        }
        return low;
    }
}

当使用mid = (low + high) / 2;的时候, 就会产生超时异常, 而换成low + (high - low) / 2的时候就成功通过

分析原因

查看一下超时的输入,理解一下原因
在这里插入图片描述
当给出的输入为n = 2126753390, bad = 1702766719
我们手动推导一下其过程(有C编译器的同学可以自己debug看看)

  • 第一次循环 low = 1, n = 2126753390 没有问题
  • 第二次循环 因为bad1702766719, 而此时的mid1063376695
    mid < bad 因此low = mid + 1
  • 第三次循环 low = 1063376696, high = 2126753390 这里就发生了问题
    int类型占四个字节, 即为32位, 补码形式最大可以表示的正数是 2 32 − 1 = 2147483647 2^{32}-1 = 2147483647 2321=2147483647 而此时low + high > 2147483647 因此会发生溢出

下面写一下这次溢出的详细过程

low = 1063376696(二进制表示) = 00111111011000011101011100111000
high =2126753390(二进制表示) = 01111110110000111010111001101110
low + high                 = 10111110001001011000010110100110

因为计算机是用补码形式表示的,且int类型只能存储32位,因此相加之后的最高位溢出变成了1 使得整体的数值成为负数, 最终导致循环始终无法结束

left + (right - left) / 2 可以通过
最大的例子就是 left=max/2
此时max/2 + (max - max/2)/2显然不会超过max 因此不会产生溢出,引起超时

正确代码

/* The isBadVersion API is defined in the parent class VersionControl.
      bool IsBadVersion(int version); */

public class Solution : VersionControl {
    public int FirstBadVersion(int n) {
        int low = 1;
        int high = n;
        while(low < high){
            int mid = low + (high - low) / 2;
            if (IsBadVersion(mid))  
                high = mid;
            else 
            low = mid + 1;
        }
        return low;
    }
}

### 数学意义与应用场景 公式 \((\text{high} - \text{low}) / 2 + \text{low}\) 表达了一种数值范围内的中间值计算方法。具体来说: - **数学意义**: 这一公式用于求解区间 [\(\text{low}, \text{high}\)] 中的中点位置。其中,\((\text{high} - \text{low})\) 计算了区间的宽度,将其除以 \(2\) 得到一半的距离,再加上下界 \(\text{low}\),从而得到该区间的中点坐标[^1]。 - **算法中的作用**: 此公式常被应用于二分查找、数值优化以及数据标准化等领域。例如,在二分查找过程中,通过此公式可以快速定位当前搜索区间的中点,进而缩小搜索空间;在数据预处理阶段,它可用于将原始数据映射至特定范围内以便后续建模或分析[^3]。 #### MATLAB 实现示例 以下是基于上述公式的简单 MATLAB 实现代码片段: ```matlab function midpoint = calculate_midpoint(low, high) % Calculate the midpoint of a given range. midpoint = (high - low) / 2 + low; end ``` #### Python 实现示例 同样地,也可以用 Python 编写类似的函数来完成这一操作: ```python def calculate_midpoint(low, high): """Calculate the midpoint of a given range.""" return (high - low) / 2 + low ``` --- ### 应用场景扩展 除了基本的数学运算外,该公式还广泛存在于以下几个领域之中: 1. **聚类分析**:当使用群智能优化算法(如 GOA 或其改进版本 D-DOGOA)解决聚类问题时,初始群体的位置可能需要均匀分布于定义域内。此时可借助此类公式生成合理的候选解集。 2. **机器学习特征缩放**:为了提高模型收敛速度及性能表现,通常会对输入变量执行归一化或者标准化处理。假设目标是把某属性从原范围变换至新标准,则可通过调整参数形式实现自定义转换逻辑。 3. **金融数据分析**:对于股票价格预测任务而言,尽管存在诸多挑战因素诸如高噪音水平和不确定性的干扰[^2],但仍然可以通过统计每日最高价 (\(H_t\)) 和最低价 (\(L_t\)), 并依据相似原理估算收盘价趋势作为辅助指标之一供决策参考之用。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Joker-Tong

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

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

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

打赏作者

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

抵扣说明:

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

余额充值