有序才能对半缩小
这一课只练一件事:在已经排好序、具有 的区间里做 。先确认能不能二分,再维护 ,每次看 丢掉一半。用 [1, 3, 5, 7, 9] 找 7 走三步,再测首尾答案,并看区间不缩小会变成 。对答案二分、lower_bound 细节和三分查找是拓展。这里不会在浏览器里运行 C++。
任务 1:先选出什么时候才能二分
不是随便对半切。必须先有 ,再用 夹住可能有答案的区间。点不认识的词可看基础解释。
必会:能判断一道题是否适合二分。这里不会在浏览器里运行 C++,只练习选择和走过程。
在 [1, 3, 5, 7, 9] 里找 7,什么时候才能二分?单调性 · 必会
left 和 right 表示什么?左右边界 · 必会
任务 2:按顺序在 [1, 3, 5, 7, 9] 里找 7
最小示例:left = 0,right = 4,mid = (left + right) / 2。按顺序点三步,先看 a[2] = 5,再看 a[3] = 7,最后确认首尾也能测到。这里不会在浏览器里运行 C++。
必会:能解释每次丢弃哪半边。边界:比较后区间必须变短;不要跳过 left = 3 这一步。
- int a[5] = {1, 3, 5, 7, 9};
- int left = 0, right = 4;
- int mid = (left + right) / 2; // 先看中点
- if (a[mid] < 7) left = mid + 1;
区间收缩走完了,现在亲手把算 的那一行敲出来:中点在 的正中间。下面是只读脚手架,只留一空给你敲键盘。
- while (left <= right) {
- int mid = ; // 取中点
- if (a[mid] < x) left = mid + 1;
- else if (a[mid] > x) right = mid - 1;
- }
int mid = (left + right) / 2; // left = 0、right = 4 时 mid = 2,正好落在中间
任务 3:测首尾答案,并看区间不缩小会怎样
建议掌握:目标可能在第一个或最后一个, 收缩时不能把端点漏掉。比较后如果 算完 left/right 仍不变,就会变成 。
必会 / 建议掌握 / 拓展:必会是判断能否二分、维护区间并丢掉一半。建议掌握是测试首尾答案,以及说明区间不缩小会死循环。对答案二分、lower_bound 细节和三分查找是拓展,现在不用当硬门槛。
- while (left <= right) {
- int mid = (left + right) / 2;
- if (a[mid] < x) left = mid + 1;
- else if (a[mid] > x) right = mid - 1;
- else return mid;
- }
先选出目标在端点时该怎么测:
再选出区间不缩小会发生什么:
任务 4:随机小测,看看你是否真的懂了
每次从本课题库抽出三道不同的选择题。题目与解析已通过校验,答完后看解析,不要只看分数;拿不准就回到对应任务再看一遍。