hyx0411

导航

C语言二分查找

C语言二分查找

一、引言

二分查找是算法入门最重要、坑最多的基础算法。

二分查找有两套标准写法:

  1. 左闭右闭区间 [left, right]

  2. 左闭右开区间 [left, right)

区间定义决定一切:初始化、循环条件、边界更新全部一一对应,不能混用。

二、二分查找前置知识

  1. 核心思想

在有序数组中,每次取中间值,通过比较舍弃一半无效区间,快速收敛答案。

  1. 硬性前提

• 数组有序(升序/降序)

• 支持下标随机访问(仅数组可用,链表不行)

  1. 所有二分Bug根源

区间定义不统一
定义什么区间,就要用对应的循环条件和边界更新,混搭必死循环。

三、写法一:左闭右闭区间 [left, right]

  1. 区间含义

[left, right]:左右两个下标都属于有效查找范围

  1. 全套标准参数(死记)

• 初始化:left = 0,right = len - 1

• 循环条件:<= right)`

• 右边缩小区间:right = mid - 1

• 左边缩小区间:left = mid + 1

  1. 完整可运行代码
#include<stdio.h>

// 左闭右闭 [left, right]
int binarySearchClose(int arr[], int len, int target)
{
    int left = 0;
    int right = len - 1;

    while (left <= right){
        // 防溢出写法
        int mid = left + (right - left) / 2;

        if (arr[< target)
        {
            // 目标在右边,mid不可能是答案
            left = mid + 1;
        }
        else if (arr[mid] > target)
        {
            // 目标在左边,mid不可能是答案
            right = mid - 1;
        }
        else
        {
            // 找到目标
            return mid;
        }
    }
    // 不存在
    return -1;
}

int main()
{
    int arr[] = {1, 3, 5, 7, 9, 11, 13};
    int len = sizeof(arr) / sizeof(arr[0]);

    int pos = binarySearchClose(arr, len, 7);
    printf("下标:%d\n", pos);

    return 0;
}
  1. 逻辑解释

• <= right:只要区间里还有数,就继续查找

• 每次判断后 mid 一定不是答案,所以直接 ±1 排除

四、写法二:左闭右开区间 [left, right)

  1. 区间含义

[left, right):left可取,right不可取
有效范围是 left ~ right-1

  1. 全套标准参数(死记)

• 初始化:left = 0,right = len

• 循环条件:while (left < right)

• 右边缩小区间:right = mid

• 左边缩小区间:left = mid + 1

  1. 完整可运行代码
#include <stdio.h>

// 左闭右开 [left, right)
int binarySearchOpen(int arr[], int len, int target){
    int left = 0;
    int right = len;
    while (left < right) {
        int mid = left + (right - left) / 2;

        if (arr < target){
            left = mid + 1;
        }
		else if (arr[mid] > target){
            // right本来就取不到,直接等于mid
            right = mid;
        }
        else{
            return mid;
        }
    }
    return -1;
}

int main(){
    int arr[] = {1, 3, 5, 7, 9, 11, 13};
    int len = sizeof(arr) / sizeof(arr[0]);

    int pos = binarySearchOpen(arr, len, 9);
    printf("下标:%d\n", pos);

    return 0;
}
  1. 关键易错点

开区间绝对不能写 right = mid - 1
因为 right 本身是无效边界,mid 已经超出合法范围,只需要把边界移到 mid 即可。

五、两种区间核心对照表(面试必背)

区间模型 区间范围 right初始值 循环条件 偏大更新 偏小更新
[L, R] 闭区间 左右都可取 <= right right=mid-1 left=mid+1
[L, R) 开区间 左可取、右不可取 len< right right=mid left=mid+1

一句话口诀:
闭区间全部取满,边界都要缩一格;开区间右端本来废,不用缩一格。

六、经典易错 Bug 总结

Bug1:mid 溢出

错误:int mid = (left + right) / 2;
正确:int mid = left + (right - left) / 2;
防止大数相加溢出。

Bug2:区间混搭(最多人错)

• 闭区间用 < right → 漏掉最后一个数

• 开区间用 right = mid - 1 → 直接越界、死循环

Bug3:边界不收缩

不写 +1 / -1,区间永远不变,直接死循环。

七、复杂度分析

• 时间复杂度:O(\log n)
• 空间复杂度:O(1)(迭代写法)

相比于遍历查找 O(n),数据量越大,二分优势越恐怖。

八、全文总结

  1. 二分查找只有两种正统区间模型,无第三种写法;

  2. 区间定义统一是解决所有死循环、错答案的核心;

  3. 闭区间适合入门刷题,开区间适合进阶源码学习;

  4. 牢记防溢出 mid 公式,坚决不写 (left+right)/2。

posted on 2026-05-18 21:26  芸歆  阅读(43)  评论(1)    收藏  举报