二分查找的死循环问题:何时mid=(left + right + 1) >> 1,何时不用

简介

二分查找计算区间中点是否满足条件,从而划分需要查找的区间。当题目具有单调性特征时,二分查找可以O(logn)的时间复杂度解决问题。在计算区间中点时,一般有两种计算方法:

mid = (left + right + 1) / 2; // 方法一
mid = (left + right ) / 2; // 方法二

什么时候需要+1,什么时候不需要,是困扰许多初学者的问题,这篇博客做一个简单的分析,帮助初学者理解记忆。

二分查找分类

二分查找分为两类:

  1. 在[left, right]中,若mid不满足条件,则解落在左侧区间,则下一次寻找的区间是[mid, right]或[left, mid - 1]。
  2. 在[left, right]中,若mid不满足条件,则解落在右侧区间,则下一次寻找的区间是[mid + 1, right]或[left, mid]。

产生这两种分类的原因是:当mid不满足条件时,下一次求解,不需要将mid放进新的区间。因此,当新区间在左侧时,right移动到mid - 1,反之left移动到mid+1。

如何决定mid

我们+1的目的,是防止死循环。而会产生死循环的原因,则是当区间只有两个元素,即left和right中间没有其他元素时,更新left或right指针后,left或right指针原地不动。

产生这原地不动的原因,是因为只有两个元素时,mid要么落在left,要么落在right。以mid落在left为例,若此时我们是第一类二分查找,新区间是[mid. right],则left指针没有改变,因而就产生了死循环。

当区间只有两个元素时,计算mid时+1,则mid会落在right,反之会落在left。因此,根据你的二分查找类型,就可以判断需不需要+1。

一句话概括

当你更新left时,left = mid,那么你需要mid = (left + right + 1) / 2。

完整模版

// mid = (left + right) / 2
int binarySearch(vector<int>& nums, int left, int right){
    while(left < right){
        int mid = (left + right) >> 1;
        if(isSolution(mid)){
            right = mid;
        }else{
            left = mid + 1;
        }
    }
    return left;
}

// mid = (left + right + 1) / 2
int binarySearch(vector<int>& nums, int left, int right){
    while(left < right){
        int mid = (left + right + 1) >> 1;
        if(isSolution(mid)){
            left = mid;
        }else{
            right = mid - 1;
        }
    }
    return left;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值