GESP5级C++考试语法知识(十七、二分算法提高篇(一))


⚔️《二分查找王国大冒险》⚔️

------真正掌握二分,不再靠"改一改试一试"


第一章:勇者小明与"百万藏宝箱"

1、很久很久以前,在"算法大陆"里,有一个叫小明的小勇者。

有一天,国王交给他一个任务:

"这里有 1000000(100万)个宝箱,只有一个箱子里藏着黄金钥匙,你要尽快找到它!"


2、小明第一反应:

"那我一个一个找呀!"

于是:

  • 第1个不是

  • 第2个不是

  • 第999999个还不是......

小明直接累趴。


3、这时候,汉克老师出现了:

"同学们,你们这样找太慢了。"

"你们需要学习一种超级强大的魔法------"

🌟二分查找!


第二章:什么叫"二分"?

1、汉克老师拿来一张按顺序写满数字的纸条:

复制代码
1 2 3 4 5 6 7 8 9 10

现在要找数字 8


(1)普通方法:

复制代码
1个个看

(2)而二分法:

复制代码
直接看中间!

(3)中间是谁?

复制代码
5

因为:

复制代码
8 > 5

(4)所以:

复制代码
左边全部不要了!

瞬间砍掉一半!


(5)只剩:

复制代码
6 7 8 9 10

(6)再看中间:

复制代码
8

找到了!


2、🌟这就是二分的威力!

(1)每次:

复制代码
砍掉一半!

(2)时间复杂度:

复制代码
O(log n)

(3)100万个数:

只需要查大约20次!


第三章:真正的本质是什么?

1、很多同学以为:

"二分就是不断找中间。"


2、❌ 错!

二分真正的本质是:

🌟寻找"分界线"!


3、比如数组:

复制代码
1 2 2 2 3

现在:

复制代码
找第一个 >=2 的位置

4、我们把每个位置变成"是否满足条件"。

(1)条件:

复制代码
a[i] >= 2

(2)于是得到:

复制代码
1   2   2   2   3
❌  ✅  ✅  ✅  ✅

(3)你发现没有?

这里有一条神奇的边界:

复制代码
❌ ❌ ❌ | ✅ ✅ ✅

(4)而二分查找:

🌟就是寻找这条边界!


第四章:二分最重要的三句话

汉克老师认真地说:


🌟第一句:你到底找什么?

你要找:

  • 第一个满足?

  • 最后一个满足?

  • 还是随便一个?

不同目标:

模板不同!


🌟第二句:mid 是答案吗?

(1)如果:

复制代码
mid可能是答案

(2)那就:

复制代码
保留mid

(3)否则:

复制代码
丢掉mid

🌟第三句:区间有没有变小?

二分最怕:

💀死循环!

原因只有一个:

复制代码
区间没缩小!

第五章:死循环怪兽登场!

1、来看:

复制代码
l = 2
r = 3

2、计算:

复制代码
mid = (2+3)/2 = 2

3、如果你写:

复制代码
l = mid;

会发生什么?


4、下一轮:

复制代码
l还是2
r还是3
mid还是2

永远不变!


5、于是:

💀进入无限死循环!


第六章:mid 的两种身份

汉克老师在黑板上写下两个点:


1、🌟左中点

复制代码
mid = (l+r)/2

例如:

复制代码
2 和 3

mid:

复制代码
2

偏左。


2、🌟右中点

复制代码
mid = (l+r+1)/2

例如:

复制代码
2 和 3

mid:

复制代码
3

偏右。


3、🌟超级重要规律!

汉克老师讲到:

"谁接mid,mid就不能站谁那边!"

什么意思?


4、如果 mid 是左中点:

复制代码
mid=(l+r)/2

那么:

复制代码
不能 l=mid

因为 mid 可能等于 l!

会卡住!


5、如果 mid 是右中点:

复制代码
mid=(l+r+1)/2

那么:

复制代码
不能 r=mid

因为 mid 可能等于 r!


6、🌟一句口诀

左中点别写 l=mid

右中点别写 r=mid


第七章:五大二分神技


⚔️第一招:找第一个 ≥ x

1、比如:

复制代码
1 2 2 2 3

找:

复制代码
第一个 >=2

答案:

复制代码
位置1

2、🌟思考

如果:

复制代码
a[mid] >= x

说明:

复制代码
mid可能是答案

所以:

复制代码
r=mid

保留它!


3、🌟代码

复制代码
int find(vector<int>& a,int x)
{
    int l=0;
    int r=a.size();

    while(l<r)
    {
        int mid=l+(r-l)/2;

        if(a[mid]>=x)
            r=mid;
        else
            l=mid+1;
    }

    return l;
}

⚔️第二招:找第一个 > x

只需要改一个地方:

复制代码
if(a[mid]>x)

⚔️第三招:找最后一个 ≤ x

这次:

复制代码
满足条件继续往右找

所以:

复制代码
l=mid+1

最后:

复制代码
答案=l-1

⚔️第四招:找最后一个 < x

和上面几乎一样。


⚔️第五招:精确查找

这个大家最熟悉:

复制代码
while(l<=r)

因为:

复制代码
左右边界都可能是答案!

代码:

复制代码
int find(vector<int>& a,int x)
{
    int l=0;
    int r=a.size()-1;

    while(l<=r)
    {
        int mid=l+(r-l)/2;

        if(a[mid]==x)
            return mid;

        else if(a[mid]<x)
            l=mid+1;

        else
            r=mid-1;
    }

    return -1;
}

第八章:为什么有时候是 l<r?

1、很多同学最迷糊:

复制代码
while(l<r)

和:

复制代码
while(l<=r)

到底区别是什么?


🌟情况1:寻找边界

(1)例如:

  • 第一个 ≥x

  • 最后一个 ≤x


(2)这种:

复制代码
答案一定存在于某个区间

(3)我们维护的是:

复制代码
[l,r)

左闭右开区间。


(4)所以:

复制代码
while(l<r)

(5)因为:

复制代码
当 l==r 时
区间已经空了

搜索结束。


🌟情况2:精确找数字

(1)例如:

复制代码
找有没有等于x

(2)此时:

复制代码
每个点都可能是答案

(3)所以:

复制代码
while(l<=r)

必须让最后一个点也检查。


第九章:真正的二分高手怎么思考?

真正厉害的人,

脑子里想的不是:

复制代码
套哪个模板?

而是:


🌟第一步

条件是什么?

例如:

复制代码
a[i]>=x

🌟第二步

哪些是❌?

哪些是✅?

例如:

复制代码
❌ ❌ ❌ ✅ ✅ ✅

🌟第三步

我要找哪条边界?

例如:

复制代码
第一个✅

🌟第四步

mid 要不要保留?

如果:

复制代码
mid可能是答案

就保留!

否则丢掉!


第十章:终极口诀

汉克老师最后送给大家的口诀:


🌟二分查找四大口诀


🌟口诀1

二分不是找数字,

而是找边界!


🌟口诀2

先想分界线:

复制代码
❌❌❌✅✅✅

再写代码!


🌟口诀3

mid包含与不包含:

mid可能是答案:

复制代码
r=mid

mid不可能是答案:

复制代码
l=mid+1

🌟口诀4

区间必须缩小!

否则:

💀死循环!


第十一章:课后挑战

1、🌟挑战1

数组:

复制代码
1 3 3 3 5 7

请找:

复制代码
第一个 >=3

答案是多少?


2、🌟挑战2

请找:

复制代码
最后一个 <=3

3、🌟挑战3

为什么下面会死循环?

复制代码
while(l<r)
{
    int mid=(l+r)/2;
    l=mid;
}

第十二章:最终奥义

真正掌握二分的人,

看到一道题时,

第一反应不是:

复制代码
"我要背哪个模板?"

而是:

🌟"这里有没有单调性?"

🌟"我在找哪条边界?"

一旦学会这个思想:

你会发现:

  • 二分答案

  • 二分最大值

  • 二分最小值

  • 二分函数

全部都能打通!

因为:

🌟所有二分,本质都一样。


相关推荐
Oj92q85H51 小时前
如何在Dev-C++中设置TDM-GCC为默认编译器
java·jvm·c++
灵智实验室1 小时前
PX4状态估计技术EKF2详解(五):EKF2 故障检测、重置与鲁棒性——从单实例到多实例仲裁
算法·无人机·px 4
programhelp_1 小时前
Roblox Coding OA 面经分享|题量不小,但整体更偏工程思维
人工智能·算法·面试
周末也要写八哥1 小时前
机器学习评价指标之平均概念
人工智能·算法·机器学习
王璐WL1 小时前
【C++进阶】多态,坑很多,面试常考!!!
c++·面试
运筹vivo@1 小时前
33. 搜索旋转排序数组(leetcode每日一题)
c++·算法
m0_629494731 小时前
LeetCode 热题 100-----27. 合并两个有序链表
数据结构·算法·leetcode·链表
todaycode1 小时前
Vue + CPP项目
javascript·c++·vue.js
玖釉-1 小时前
Slang 和 HLSL 的区别与用法详解:现代图形渲染中的两种 Shader 编程语言
c++·算法·图形渲染