首页 > 其他分享 >二分

二分

时间:2023-08-13 19:14:05浏览次数:25  
标签:二分 int mid 满足 答案 区间

二分

介绍

相信大家小时候都玩过猜数字的游戏,一般来说,大家都是从中间开始猜,比如猜0~100之间的整数,先猜50,小了再猜75,大了再猜35。我们在玩这个游戏时就使用了二分这个思想,在算法竞赛中,我们对具有单调性的问题便可以使用二分,是一种非常好用的算法,但是二分里面的坑也非常多,稍有不慎便会漏掉答案或陷入死循环

整数二分

此为二分的示意图,我们在对问题进行求解的时候,先分析问题中有什么性质可以利用,根据这个性质找两个区间的边界,使得左边不满足或满足这个性质,右边满足或不满足这个性质,注意两个区间并没有交点(一个点不可能既满足又不满足)

根据区间究竟满足还是不满足,二分也有两个模板(一种 \(mid\) 落在左区间,另一种 \(mid\) 落在右区间):

第一种模型

这种模型 \(mid=(l+r)/2\),这里无需考虑边界。

int bsearch_1(int l, int r)
{
    while (l < r)
    {
        int mid = l + r >> 1;
        if (check(mid)) r = mid;    // check()判断mid是否满足性质
        else l = mid + 1;
    }
    return l;
}

判断 \(mid\) 是否满足性质:
如果满足说明答案包括 \(mid\) \(r=mid\)
如果不满足说明答案包括 \(mid\) \(l=mid+1\)

第二种模型

这种模型的 \(mid = (l+r+1)/2\) 。这里因为计算机会自动去尾,例如当 \(l=0,r=1\) 时,如果不加一 \(mid\) 便会变成0,\(l=mid\) ,便会陷入死循环

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;
}

判断 \(mid\) 是否满足性质:
如果满足说明答案包括 \(mid\) \(r=mid\)
如果不满足说明答案不包括 \(mid\) \(l=mid+1\)

浮点数二分

浮点数二分相对简单,不像整数二分需要考虑边界问题

精度问题

两种方式:

  • 设置一个精度 \(eps\) 循环条件是 \(r-l>eps\) 保留 \(k\) 位小数时 \(eps=10^-\)\(^(\)\(^k\)\(^+\)\(^2\)\(^)\)
  • 循环100次

每次根据 \(mid\) 确定是 \(r=mid\) \(l=mid\) 还是 \(l=mid\) \(r=mid\) 就行了

如何使用

关于无解的判断

\((l+r+1)/2\) \(mid\) 取不到 \(l\),因为 \(l=mid+1\) ,当 \(l=r\) 就退出,假设 \(mid\) 能取到 \(r\) ,那么 \(l=r+1\),与循环退出的条件不符

\((l+r)/2\) \(mid\) 取不到 \(r\),原因同上

两种判断方法:
因为二分保证有解,在循环结束时一定停在一个点上,所以衍生出了两种方法:
1、看这一个点是否满足要求,不满足就无解

2、\((l+r+1)/2\) 将原本 \([1,n]\) 的区间扩大到 \([1,n+1]\),如果最后停在了越界的下标上说明无解(其他点都不满足要求)

​ \((l+r)/2\) 将 \([1,n]\) 扩大到 \([0,n]\),与上一个同理

适用场景

区间 \([l, r]\) 被划分成 \([l, mid]\) 和 \([mid + 1, r]\) 时使用 第一个模板

区间 \([l, r]\) 被划分成 \([l, mid - 1]\) 和 \([mid, r]\) 时使用 第二个模板

\((l+r)/2\) 适用于左区间不满足,右区间满足

\((l+r+1)/2\) 适用于左区间不满足,右区间满足

例题引入

给定一个数组,数组里的元素从小到大递增,找到 \(\geq x\) 的数中最小的一个

给定一个数组,数组里的元素从小到大递增,找到 \(\leq x\) 的数中最小的一个

详解:
当我们遇到最大最小这类字眼的时候,一般要使用二分,当然,二分有两个模板,究竟如何考虑呢

首先,数组是单调递增的,我们可以使用二分

如果要找 \(\leq x\) 的数,那么这个数应该比较小,我们应该在左边查找,所以我们使用第一个模板

如果要找 \(\geq x\) 的数,那么这个数应该比较大,我们应该在右边查找,所以我们使用第二个模板

二分查找

二分查找也被叫做折半查找,顾名思义,就是每次查找去掉不符合条件的一半区间,直到找到答案(整数二分)或者和答案十分接近(浮点二分)。在阅读题面时,我们要关注题目是最小值最大化还是最大值最小化

二分答案

二分答案适用于当答案属于一个区间,这个区间比较大,直接暴力会超时,最重要的是区间满足单调性,当这个答案越大(或越小),题目中的一个变量也会随之增大(或减少),通过check函数进行检验答案是否正确,根据结果放弃右半部分或左半部分

标签:二分,int,mid,满足,答案,区间
From: https://www.cnblogs.com/xiaozhu0602/p/17626998.html

相关文章

  • C++STL库 二分查找,以及对set集合进行二分查找,来源于”leetcode7022. 限制条件下元素之
    C++的头文件<algorithm>中有用于二分查找的函数,lower_bound()、upper_bound()以及binary_search():lower_bound():返回大于等于目标值的第一个位置upper_bound():返回大于目标值的第一个位置,binary_search():若目标值存在则返回true,否则返回false参数列表:(起始位置,结束位置,目标值) ......
  • 二分板子
    1.求最大值最小while(l<=r){  mid=(l+r)>>1;  if(check(mid))ans=mid,r=mid-1;    elsel=mid+1; }例题洛谷p3853路标设置code#include<bits/stdc++.h>usingnamespacestd;intl,n,k,a[100010],r,ll,mid,ans,cnt;boolcheck......
  • 简单使用二分查找法
    #include<stdio.h>intmain(void){ intarr[]={1,2,3,4,5,6,7,8,9,10}; intsz=sizeof(arr)/sizeof(arr[0]);//元素个数 intNumber=5;//需要查找的值 intright=sz-1;//右下标 intleft=0;//左下标 while(left<=right){ inthalf=(right+l......
  • 代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素
    704二分查找题目给定一个n个元素有序的(升序)整型数组nums和一个目标值target,写一个函数搜索nums中的target,如果目标值存在返回下标,否则返回-1。第一想法判断条件是value=target因为数组是升序,其实每种查找方法应该相差不大?不过题目都标了二分查找了emmm思......
  • 月度开销--二分法
    【题目描述】农夫约翰是一个精明的会计师。他意识到自己可能没有足够的钱来维持农场的运转了。他计算出并记录下了接下来N(1≤N≤100,000)天里每天需要的开销。约翰打算为连续的M(1≤M≤N)个财政周期创建预算案,他把一个财政周期命名为fajo月。每个fajo月包含一天或连......
  • ABC245E Wrapping Chocolate [线段树二分]
    也许更好的阅读体验\(\mathcal{Description}\)\(n\)个物品有长和宽,\(m\)个盒子也有长和宽,一个盒子最多可以装一个物品,问\(n\)个物品能否都放进盒子,物品和盒子不能旋转\(\mathcal{Solution}\)先离散化长和宽,将物品和盒子按照长从大到小排序考虑到当前物品时将所有长大于等于当......
  • 二分答案,二分搜索,封装
    namespacebinarySearch{ //最后一个小于等于 template<typenameT> T*binarySearchLastSmall(T*l,T*r,intkey){ while(l+1<r){ T*mid=l+(r-l)/2; if(*mid<=key)l=mid; elser=mid; } returnl; } //最后一个小于 template<typenameT>......
  • 二分图与匹配 I :二分图的最大匹配
    引入:什么是二分图,什么是匹配口头语言描述:一个图,你把他的点集划为两个集合,让每个集合之间的点没有连边,就是一个二分图。二分图的一个等价定义是:不含有奇数条边的环的图就是一个二分图。证明:显然,观察每一条路径,都是从一个点集走向另外一个点集,则一个环必定得走偶数次。匹配,则......
  • 二分图相关定理
    最长反链:一张有向无环图的最长反链为一个集合\(S\subseteqV\),满足对于\(S\)中的任意两个不同的点\(u,v\inS(u\nev)\),\(u\)不能到达\(v\),\(v\)也不能到达\(u\),且\(S\)的大小尽量大最小不可重链覆盖:在DAG中选出若干条链,经过每个点一次,且链数尽量少最小点覆盖:......
  • 7-18 二分法求多项式单根 (20分)
    7-18 二分法求多项式单根 (20分)二分法求函数根的原理为:如果连续函数f(x)在区间[a,b]的两个端点取值异号,即f(a)f(b)<0,则它在这个区间内至少存在1个根r,即f(r)=0。二分法的步骤为:检查区间长度,如果小于给定阈值,则停止,输出区间中点(a+b)/2;否则如果f(a)f(b)<0,则计算中点的值f((a+b)/2)......