信息竞赛中的一些算法:二分查找

物理
信息竞赛中的一些算法:二分查找

用户头像
世界是一个巨大的状态转移方程对吗 更新于2025-7-2 09:34:15

这是一个关于信息竞赛的帖子(应该可以发在 O-Box 里吧)

符号约定:

$A\to B$ 表示把 $A$ 的值设为 $B$。

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

一位学生背着一个装了 $n$ 本书的背包,走出了图书馆。

这时,警报器响了。学生打开背包,拿着其中一本书走过大门,警报器没响。

他拿起另一本书,走过大门,警报器还是没有响。

保安有些不耐烦了,他把书分成两份,拿起其中一半,走过大门,警报器响了。

他把这一半书再次分为两份……

很快,保安找到了那本书。他用鄙视的眼光看着学生:“你难道不知道 $O(\log n)$ 比 $O(n)$ 快吗?”

第二天,图书馆丢失了 $n-3$ 本书。

--------------------------------------------------------

这个故事讲的不是二分查找的原理和优缺点,是为了说明二分查找更快。

假设我们有一些排好序的数据,想从中找出你想找的数,就可以用二分查找。

假设数据是这样的:

0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7(冒号左边是编号,右边是数据)

假设你想找到 $2$,怎么办呢?

先定义 $l\to0,r\to8$ 表示寻找的范围,一开始肯定是全部。(注:范围包括 $l$ 不包括 $r$)

然后定义 $m\to[\frac{l+r+1}{2}]=4$ 作为这个区间最中间的数($[x]$ 是 floor 函数)

比较 $2$ 与第四个数 $4$ 的大小:$2\lt4$

然后 $r\to4$

$m\to[\frac{l+r+1}{2}]=2$

比较 $2$ 与第二个数 $2$ 的大小:$2=2$

于是查找完成。

不完整代码:

int a[8] = {0, 1, 2, 3, 4, 5, 6, 7}

int l = 0, r = 8;

while (a[m] != 2) {

    m = (l + r + 1) / 2;

    if (a[m] > 2) {

        r = m;

    } else if (a[m] < 2) {

        l = m + 1;

    }

}

cout << "a[" << m << "] = 2" << endl;


当然,我们可以继续优化……

假设有 $2^n$ 个数,最慢需要循环 $n$ 次。易得:

有 $\frac12$ 的可能循环 $n$ 次;

有 $\frac14$ 的可能循环 $n-1$ 次;

有 $\frac18$ 的可能循环 $n-2$ 次;

有 $\frac{1}{2^k}$ 的可能循环 $n-k+1$ 次。

求个平均值:

$\sum_{k=1}^{n+1}\frac{1}{2^k}\cdot(n-k+1)$

$=\sum_{k=1}^{n+1}\frac{1}{2^k}\cdot{n}-\sum_{k=1}^{n+1}\frac{1}{2^k}\cdot(k-1)$

$=n-\sum_{k=1}^{n+1}\frac{k-1}{2^k}$

$\gt n-2$

也就是循环次数的平均数大于 $n-2$。

如果把代码改成这样:

int a[8] = {0, 1, 2, 3, 4, 5, 6, 7}

int l = 0, r = 8;

while (l<r) {

    m = (l + r + 1) / 2;

    if (a[m] > 2) {

        r = m;

    } else {

        l = m + 1;

    }

}

cout << "a[" << m << "] = 2" << endl;

这样也可以实现查找。

虽然它每次一定循环 $n$ 次,但它每次循环可以减少 $1$ 次比较,当 $n$ 较大时更快。

收起
6
2
共4条回复
时间正序
应该是丢了n-3本
1条评论
用户头像
世界是一个巨大的状态转移方程对吗
11天前

是的,谢谢提醒

出错的 $\LaTeX$:
$\sum_{k=1}^{n+1}\frac{1}{2^k}\cdot(n-k+1)\\=\sum_{k=1}^{n+1}\frac{1}{2^k}\cdot{n}-\sum_{k=1}^{n+1}\frac{1}{2^k}\cdot(k-1)\\=n-\sum_{k=1}^{n+1}\frac{k-1}{2^k}\\\gt{n-2}$

你应该是把\gt n写成了\gtn

注意空格分开!

你把那个出错的$\LaTeX$源码给我看一下,不要打“$”
还有换个头像,容易被当成@美丽乡村(暑假我就杀回来了等着吧被喷
说到这我又担忧起论坛暑假会不会变成大唐盛世😭
1条评论
用户头像
世界就是一条巨大的流水线对吗 回复 世界是一个巨大的状态转移方程对吗
11天前

你似乎已改。。。