[leetcode] First Bad Version

本文详细介绍了在二分查找算法中如何安全地求取中间值,避免整数溢出的问题,并提供了两种实现方式:非递归和递归。通过分析代码,读者可以理解如何正确地计算中间值并应用于实际问题。

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

You are a product manager and currentlyleading a team to develop a new product. Unfortunately, the latest version ofyour product fails the quality check. Since each version is developed based onthe previous version, all the versions after a bad version are also bad.

Suppose you have n versions [1, 2, ..., n]and you want to find out the first bad one, which causes all the following onesto be bad.

You are given an API bool isBadVersion(version) which will return whether version is bad. Implement afunction to find the first bad version. You should minimize the number of callsto the API.

Credits:

Special thanks to @jianchao.li.fighter foradding this problem and creating all test cases.


题目大意是找到第一个不符合要求的版本号,因为版本号有序,因为题目要求最少次数调用 isBadVersion(version)函数,所以很容易想到二分查找。但是这题有个陷阱,这也是为什么写这篇博客的原因。大家熟悉的二分查找,在求中间位置的时候,都是 mid = (start + end)/2; 但这是有问题的,假设mid,start,end全为int型,当数组长度较大(即end可能会很大),而要查找的值的位置也比较接近end,或者要找的数就是最后一个数。此时 start  也会变得很大,这样mid很有可能超过了int的表示范围。解决这个问题很简单,但是忽略这个问题也特别简单。其实这个问题可以避免,就是我们换一种方式求mid,即 mid = start + (end - start)/ 2 。我们来分析一下这个式子,因为mid,start,end全是int型,所以end-start肯定是int型,而(end-start)/2当start和end比较接近时结果较小,此时start可能会很大,但因为end没有超过int型的表示范围,则start+(end - start)/2也不会超过。同样的道理,当end和start离的很远时也不会超过。这就是比较安全的求mid的方法。

还有一种不太推荐的方法可以防止start+end的和溢出,就是我们可以扩大类型,把mid,start,end全换成long long int即可。下面给出这两个方法的代码,一个非递归,一个递归。

方法一:

bool isBadVersion(int version);

class Solution {
public:
    int firstBadVersion(int n) {
        int s = 1;
        int e = n;
        while (s <= e)//注意这个等号
        {
            int mid = s + (e - s)/2;
            if (isBadVersion(mid))
            {
                e = mid - 1;
            }
            else
                s = mid + 1;
        }
        
        return s;
    }
};

方法二:

bool isBadVersion(int version);

class Solution {
public:
    void helper(long long int s,long long int e,long long int * ret)
    {
        if (s > e)
        {
            return ;
        }
        
        long long int  t = s + e;
        long long int mid = t / 2;
        if (isBadVersion(mid))
        {
            *ret = mid;
            helper(s,mid-1,ret);
        }
        else
            helper(mid+1,e,ret);
    }
    int firstBadVersion(int n) {
        int s = 1;
        int e = n;
        long long int ret;
        long long int * p = &ret;
        helper(s,e,p);
        return ret;
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值