首页 > 其他分享 >二分

二分

时间:2023-10-17 09:05:58浏览次数:26  
标签:二分 mid 区间 答案 序列 单调

二分

二分是一种基于一个具有非严格单调性的序列上进行搜索的算法,其复杂度为 \(O(logn)\),在单调性的前提下,效率碾压遍历不知道多少倍。

原理

我们以下图中长度 \(n=10\) 的非严格单调递增序列 \(P\) 为例

假设此时我们询问一个数 \(x\),我们需要在序列中找到一个数 \(y\) ,使得 \(y\) 是整个序列中所有大于等于 \(x\) 的树中最小的,即 \(y=\min\left \{ i \right \}[i \in P ,i \ge x]\)。

现在思考如何找到这个数 \(y\) 。

一种极其明显的思路是,从 \(i=1\) 处开始遍历至 \(i=10\) 处,遍历过程中实时维护变量 \(sum\) 。

for(int i=1;i<=10;i++)
{
	if(P[i]>=x) sum=min(P[i],sum);
}

当然由于序列 \(P\) 单调递增,你完全可以在找到第一个大于等于 \(x\) 的数后立刻退出循环,但是尽管如此也不能改变复杂度为 \(O(n)\) 的事实。

如果我们想 \(O(logn)\) 地找 \(y\) 怎么办?

二分!

现在我们定义两个指针变量 \(L=1,R=10\),代表此时答案会包含在此区间内,同时算出区间 \([L,R]\) 的中点 \(mid\) (向下取整),如图

此时我们判断 \(mid\) 所在值 \(P[mid]\) 是否满足大于等于 \(x\) ,若满足,则根据序列 \(P\) 单调递增的性质,可得大于 \(x\) 中最小的树必定在区间 \([mid,R]\) 中,此刻我们更新 \(L=mid\),并进入下一次二分

若不满足,则答案必定位于区间 \([L,mid-1]\),为什么是 \(mid-1\)?,因为值 \(P[mid]\) 并不满足我们的条件,因此在下一次二分时,我们的答案区间不能包含 \(mid\)。此时更新 \(R=mid-1\)。

那么我们如何知道是否找到答案了呢?

在上面的过程可知,我们二分的区间总满足 \(L<R\) ,这是必然的,若 \(L=R\) 了,则证明二分结束,找到答案或答案不存在,因此我们要用一个while语句将二分过程囊括起来,而while的循环条件就设为 \(L<R\)。因为最终 \(L=R\) ,所以我们只需要输出 \(L\) 即可。且此刻 \(\forall i < mid\),有 \(P[i] < x\); \(\forall i \ge mid\),有 \(p[i] > x\)。

最终的答案会有三种情况:

  • \(L\in [1,n]\)

证明答案存在

  • \(L > n\)

证明答案不存在,且此时序列 \(P\) 中所有值都小于 \(x\)

  • \(R = 1\)

此刻你需要判断 \(P[R]\) 是否大于等于 \(x\),以此判断答案的存在性。(事实上你可以在最初初始化指针变量 \(L,R\) 时把 \(L\) 设为 \(0\),最终答案不存在的情况就会变成 \(R=0\))

代码

二分有多种不同的模板,其区别大多仅在于循环条件与 \(mid\) 计算上,使用时需要根据具体情况合理修改条件即可。

以下是上面的例子的代码,也是最通用的二分模板

int L=0,R=n;
while(L<R)
{
	int mid=(L+R)/2;//or mid=(L+R)>>1;
	if(P[mid]>=x) L=mid;
	else R=mid-1;
}
printf("%d",P[L]);

例题

(updating......)

标签:二分,mid,区间,答案,序列,单调
From: https://www.cnblogs.com/AnEasySong/p/er-fen.html

相关文章

  • 二分图备忘录
    本文是写给作者自己看的概念指一张无向图G中,N个节点可以划分为两个集合A,B集合A和B内部没有连边,A和B可以有连边(可以有空集)Q:为什么不用三分图:A:很简单,三分图分类更多,更麻烦。没有顺序关系有三种情况,有顺序关系则是六种(就像线段树不用三叉)一些叫法A集合内的点:左部点B集合内的......
  • 折半(二分)查找算法—高效搜索算法
    折半查找算法(BinarySearchAlgorithm)是一种高效的搜索算法,常用于已排序的数组或列表中进行查找操作。它的核心思想是通过比较中间元素与目标值的大小关系来确定目标值在数组的哪一部分,从而缩小搜索范围。本文将详细介绍折半查找算法的原理、实现以及应用场景。一、原理折半查找算......
  • 判断二分图的方法
    题目描述:龙龙得知2020年中国将有2000万至4000万男人娶不到老婆后。他打算好好调查一下是不是人们的感情出现问题。他对n个人进行调查,得到m条信息,每条信息表示为某两人曾经是情侣。由于他不知道这些人的性别,请你帮他判断一下,有没有同性是情侣的情况?对于100%的数据,n的范围[2,100000......
  • 二分模板
    整数二分边界boolcheck(intx){/*...*/}//检查x是否满足某种性质//区间[l,r]被划分成[l,mid]和[mid+1,r]时使用:intbsearch_1(intl,intr){while(l<r){intmid=l+r>>1;if(check(mid))r=mid;//check()判断mid是......
  • 算法0506 对数器 二分搜索
    对数器非常重要的自我验证代码正确性的方法在面试时或机试时写算法题,没有测试用例或者测试用例太少,导致巨大的数据量无法进行测试时。需要自己写测试用例数据时可以使用对数器。......
  • 学习C语言心得-自定义函数-对整形有序数组进行二分查找-二分法
    对整形有序数组进行二分查找#include<stdio.h>intfind(intarr[],intsz,intk){ intleft=0;intright=sz-1; while(left<=right) { intmid=left+right/2; if(k>arr[mid]) { left=mid+1; } if(k<arr[mid]) { right=mid......
  • 二分查找(浮点二分)
    一、算法简介浮点数二分相比与整数二分就要简单很多了,但是还是要注意范围的问题。以下给出一个小例子,求\(x\)的平方根,\(x\)的范围在\([0,10000]\)内:#include<iostream>#include<cmath>usingnamespacestd;intmain(){doublen;cin>>n;dou......
  • LeetCode704. 二分查找
    描述给定一个n个元素有序的(升序)整型数组nums和一个目标值target,写一个函数搜索nums中的target,如果目标值存在返回下标,否则返回-1。示例1输入:nums=[-1,0,3,5,9,12],target=9输出:4解释:9出现在nums中并且下标为4示例2输入:nums=[-1,0,3,5,9,1......
  • 【二分图】第1幕:初识
    二分图的概念第1幕·第1场·二分图的概念定义若有一个无向图,其所有节点可以被分为两个不相交的非空集合,且同一集合中的点之间没有边,那么称该图为二分图。形式化地,对于一张图\(G=\{V,E\}\),若有集合\(A,B\)满足:\((A,B\subseteqV)\and(A\capB=\emptyset)=1\)\(\fora......
  • 二分答案作题心得
    使用洛谷P1873举例看出这个题目考的是二分答案找出题目横纵坐标,横坐标是我们要输出的东西(也是L和R),纵坐标是输入的m,理解题目,观察横纵坐标的递增递减关系这个题目里面输入的m是所得到的木材,横坐标是锯片的高度,锯片越高得到的木材越少,所以是递减关系开始写二分模板,写check函......