这篇博客主要讲解二分模板,具体的二分原理可以去搜二分法原理博客
整数二分可以分为两个模板,注释有解释
模板一:
int l = 0; int r = 1e6 + 10//一个比较大的数就行
void check(int middle) {
//具体代码看题
}
while (l < r) {
int mid = (l + r+1) / 2;//为什么加1呢?后文讲解
if (check(mid)) {//让满足check函数的值控制在[l,mid]之间(两头能取到)
l = mid;//所以mid可能会是答案
//返回值为真 则答案在[l,mid]之间(两头可以取到)
}
else r=mid-1//减1是因为此时mid不可能是答案
}
//至于为什么会是(l+r+1)
//是因为若l+1==r的话mid=(l+r)/2然后向下取整,那么mid就等于l
//l的值永远不会更新导致死循环
模板二:
int l = 0;
int r = 1e6 + 10;
void check(int middle) {
}
while (l < r) {
int mid = l+r>>1//除以二的意思
if (check(mid)) {//满足check函数的值都控制在[l,mid]
r = mid;//缩小搜索范围
}
else l=mid+1//取不到mid这个值
}
//这个不用加一的原因是c++默认整除时向下取整
整数二分例题(来源:力扣):
题目:
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
请必须使用时间复杂度为 O(log n)
的算法。
示例 1:
输入: nums = [1,3,5,6], target = 5 输出: 2
示例 2:
输入: nums = [1,3,5,6], target = 2 输出: 1
AC代码:
class Solution {
public:
int searchInsert(vector<int>& nums, int target)//题目给的 {
int n = nums.size();
int x = target;//更方便书写
int l = 0;int r = n-1;
if(nums[r]<x)return n;//若测试数据大于数组中最大下标的值,下面的循环最大只能到n-1的下标,所以要单独处理
while(l<r){
int mid=(l+r)/2;
if(nums[mid]>=x)r=mid;
else l = mid+1;
}//模板二
return l;
}
};
浮点二分:
浮点二分的话相较于整型二分更简单,边界问题没那么细,相信大家做做例题就明白了,就是要注意退出循环的条件要改改(L<R)改为(R-L>1e-6)