关于 m = l + (r - l + 1) / 2 的问题

关于 m = l + (r - l + 1) / 2 的问题

波波老师,在程序中出现死循环是因为 r 和 l 相邻造成的。按照您的处理方式,只要是 r-l == 奇数的情况,m 的取值都会比之前大 1,这固然可以解决 r 和 l 相邻带来的问题,但是理解起来是不是会更费力一些?如果这么写  int mid = r-l == 1 ? l + (r - l + 1) / 2 : r 是不是会更好理解?这样就能清楚地知道 r 和 l 相邻时有需要注意的情况,不过比起您那样写确实少了几分优雅。

正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

1回答
liuyubobobo 2020-09-10 16:53:50

赞思考!


其实,按照你的思路,这样写就 ok:int mid = r - l == 1 ? r : l + (r - l) / 2;

这样一来,表示 l 和 r 不相邻的时候,取中值的方式还是普通的方式,但是一旦 l 和 r 相邻,取右侧的值,来处理死循环的问题。


课程后续,我会推荐 Leetcode 的探索,其中,给出了一个模板,是这样的:

int binarySearch(vector<int>& nums, int target){
    
    if (nums.size() == 0)
        return -1;
    
    int left = 0, right = nums.size() - 1;
    while (left + 1 < right){
        // Prevent (left + right) overflow
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid;
        } else {
            right = mid;
        }
    }
    
    // Post-processing:
    // End Condition: left + 1 == right
    if(nums[left] == target) return left;
    if(nums[right] == target) return right;
    return -1;
}


注意,这个代码不是在求 lower,而是在做查找,但是我们可以用这个思路将其改造成 lower 或者 upper。

这个代码的关键是,while 的条件是 left + 1 < right,换句话说,在 left + 1 == right,即 left 和 right 相邻的时候,退出循环,之后,在循环外,分别对 left 和 left + 1(即 right)进行验证,使用这种方式来处理 left 和 right 相邻的时候可能出的问题。


我觉得这两个思路都是 ok 的,其实都是意识到了 left 和 right 相邻的时候可能出问题,对他们进行特殊处理。在这个思想基础上,他们代码的逻辑都是正确的,我认为你应该采取你觉得可读性最强的,最好理解的代码:)


不过,可读性强,易理解,并非是一个客观标准,每一个人的想法不一样,每一个团队的标准也不一样,在这种情况下,只要选择一个大家(或者自己)都能接受的写法就好了:)我的课程只是把我常用的一个方法呈现给大家:)


感谢你提供的思路。非常赞!继续加油!:)

问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
算法与数据结构
  • 参与学习       2583    人
  • 解答问题       1082    个

慕课网算法名师Liuyubobobo,5年集大成之作 从0到工作5年,算法与数据结构系统解决方案

了解课程
请稍等 ...
意见反馈 帮助中心 APP下载
官方微信

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师