二分算法的实践总结.
#include<bits/stdc++.h> using namespace std; // 整数二分算法模板 —— 模板题 AcWing 789. 数的范围 bool check(int x) {/* ... */} // 检查x是否满足某种性质 // 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用: //也就是每次查找如果我们要把符合的东西, 在他左边继续找.那么mid成功了我们就区间变成[l,mid] int bsearch_1(int l, int r) { while (l < r) { int mid = l + r >> 1;//取一半偏左的.因为只有这样才分得均匀. 否则你取中间偏右一点的. 那么 [l,mid] 就明显比 [mid+1,r] 长度大. 分得均匀越不容易出错. if (check(mid)) r = mid; // check()判断mid是否满足性质,我们就在他左边继续找. else l = mid + 1; } return l; } // 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用: int bsearch_2(int l, int r) { while (l < r) { int mid = l + r + 1 >> 1; if (check(mid)) l = mid; else r = mid - 1; } return l; } // 作者:yxc // 链接:https://www.acwing.com/blog/content/277/ // 来源:AcWing // 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 //problem1: bool check1(int x) {return x>3;} int bsearch_11(int l, int r) { while (l < r) { int mid = l + r >> 1; cout<<"=============="<<endl; cout<<mid<<endl; //4 cout<<l<<endl; //3 cout<<r<<endl; //4 if (check1(mid)) r = mid; else l = mid + 1; } return l; } bool check2(int x) {return x<3;} int bsearch_22(int l, int r) { while (l < r) { int mid = l + r + 1 >> 1; if (check2(mid)) l = mid; else r = mid - 1; } return l; } int main(){ puts("第一个问题我们找区间里面比a大的数里面最小的"); puts("因为我们找到匹配的后,要在他左边继续寻找所以我们用模板1"); cout<<bsearch_11(0,7)<<endl; puts("第2个问题我们找区间里面比a小的数里面最大的"); puts("因为我们找到匹配的后,要在他左边继续寻找所以我们用模板1"); cout<<bsearch_22(0,7)<<endl; // 最后我们来理解一半的思想. //假设我们对1234做二分查找. 那么我们mid=2.5 //假设我们不做[1,2] [3,4] 的划分. 我们做[1] [2,3,4] 的划分. //其实这种不管好坏,首先效率就达不到最优. }