二分查找模板

1.什么是二分查找?

首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。

2.二分查找的两个模板

1.当我们将区间[l, r]划分成[l, mid]和[mid + 1, r]时,其更新操作是r = mid或者l = mid + 1;,计算mid时不需要加1。

int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;
        else l = mid + 1;
    }
    return l;
}

2.当我们将区间[l, r]划分成[l, mid - 1]和[mid, r]时,其更新操作是r = mid - 1或者l = mid;,此时为了防止死循环,计算mid时需要加1。

int bsearch_2(int l, int r)
{
    while (l < r)
    {
        int mid = l + r + 1 >> 1;
        if (check(mid)) l = mid;
        else r = mid - 1;
    }
    return l;
}

模板1和模板2是根据区间来划分的,用到哪个区间对应哪个mid,而区间的判断有if里的具体条件判断。
比如下题:

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。


示例 1:

输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
示例 2:

输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1
 

提示:

你可以假设 nums 中的所有元素是不重复的。
n 将在 [1, 10000]之间。
nums 的每个元素都将在 [-9999, 9999]之间。


我写的题解如下:

int search(int* nums, int numsSize, int target){
    int l = 0,r = numsSize - 1,mid,target_num;

    while(l < r)
    {
        mid = (l+r)/2;
        if(nums[mid] >= target) r = mid;
        else l = mid + 1;
    }
    if(nums[l] == target) target_num = l;
    else target_num = -1;
    return target_num;

}

if里面的check为nums[mid] >= target,所以找到该target在左半区间并且包含mid,即r = mid,相反,如果nums[mid] < target ,则 l = mid +1,不包含mid。所以使用模板1,mid = (l+r)/2.

改变if里面的值为nums[mid] <= target,则变为模板2:

int search(int* nums, int numsSize, int target){
    int l = 0,r = numsSize - 1,mid,target_num;

    while(l < r)
    {
        mid = (l+r+1)/2;
        if(nums[mid] <= target) l = mid;
        else r = mid - 1;
    }
    if(nums[l] == target) target_num = l;
    else target_num = -1;
    return target_num;

}

可见具体使用哪个模板,得先根据条件判断它具体区间,然后确定mid的值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值