二分查找的详细分析--基于循环不变式的分析

本文详细分析了二分查找算法,包括基本的流程、朴素实现、循环条件解释和循环不变式分析。重点探讨了目标值存在与不存在时的循环不变式,并对变形如下界、上界及寻找旋转数组最小值问题进行了讨论。总结了二分查找的本质是分治和区间收缩,强调了处理边界问题的重要性。

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

二分查找:

1. 基本二分查找

给一个数组,已升序排序,即不存在重复元素,查找给定值target,如果不存在,返回该值在数组中可以插入的位置。二分查找本质是利用分治加剪枝不断进行问题规模的缩小,到最后问题不可分解决问题。将一个区间分为两半(缩小规模),分别查找,因为另一个子问题肯定无解,不需要查找(剪枝),所以本质是剪枝的分治。另外对二分查找循环不变式分析的过程要按查找值存在与否分类讨论,且随着迭代的深入,区间大小始终是在减半收缩。

1.1. 流程

1)将查找区间一分为二,选取中间点,若是要查找元素,返回
2)如果中间点小于target值,查找右半区间,从 mid + 1 到 right
3)若中间点大于target值,查找左半区间,从 left 到 mid - 1
4)如果区间不存在,即left > right ,结束。

1.2. 朴素实现
int binary_search(int *arr, int size, int target) {
  int l = 0, r = size - 1;
  while (l <= r) {
    int mid = l + (r-l) / 2;
    if (arr[mid] == target) {
      return mid;
    } else if (arr[mid] > target) {
      r = mid - 1;
    } else {
      l = mid + 1;
    }
  }
  return l;
}
1.3. 分析
1.3.1 循环条件解释

因为循环的本质是在进行区间的收缩,因为对于一个target来说,肯定要么在左半区间,要么在右半区间,或者刚好在区间中间点(会直接返回),其他情况都需要不断查找target在哪个半区间,而区间最小的情况是只有一个元素,即 [ l e f t , l e f t ] [left, left] [left,left]或者 [ r i g h t , r i g h t ] [right,right] [right,right]

1.3.2 循环不变式

循环不变式分为两种情况讨论,如果target在数组中,如果target不在数组中
1. target在数组中
target一定在区间 [ l e f t , r i g h t ] [left, right] [left,right]中。

  • 初始情况
    target值一定在区间 [ l e f t , r i g h t ] [left,right] [left,right]中。
  • 迭代
    将区间一分为二,如果mid所指值小于target,因为target存在,那么target一定在 [ m i d + 1 , r i g h t ] [mid + 1, right] [mid+1,right]右半区间,如果mid所指的值大于target,同理target的值一定在 [ l e f t , m i d − 1 ] [left, mid - 1] [left,mid1]的左半区间,通过不断的收缩区间大小为原来一半,不断缩小搜索范围
  • 终止
    可以知道最终left会等于right,此时由不变式分析,target一定在 [ l e f t , r i h g t ] [left,rihgt] [left,rihgt]区间,此时区间只有一个数一定是target。

2. target不在数组
循环不变式: 如果要插入target则一定插入在区间中的某个位置,要么就是插入在left,或者插入在right之后。

  • 初始情况
    初始情况右三种:

    • I. target在数组下标left之前
      此时区间中所有值均大于target,target插入必定插入在left
    • II. target在数组right之后
      此时target大于数组中所有值,插入一定插入在right之后
    • III. target在数组中某两个数之间 [ i , i + 1 ] [i, i + 1] [i,i+1]
      此时插入一定是插入在数组中间
  • 迭代

    • I. target在数组left之前
      此时区间中所有的数均大于target,所以一直查找 [ l e f t , m i d − 1 ] [left, mid - 1] [left,mid1]左半区间。left始终不变,插入位置在left。
    • II. target在right之后
      此时区间中所有数都小于target,一直查找 [ m i d + 1 , r i g h t ] [mid + 1, right] [mid+1right]右半区间,right不变,插入位置在right之后。
    • III. target在数组中某两个数之间 [ i , i + 1 ] [i,i+1] [i,i+1]
      此时分类:
      • m i d > i + 1 mid > i+1 mid>i+1
        [ i , i + 1 ] [i,i+1] [i,
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值