算法与思想——二分查找与二分答案
算法与思想——二分查找与二分答案
@
一、二分算法-----log2n速度
1.二分前提:有序的数列,,整体成升序或降序,可以中间有相等的数值。
2.二分写法:定义寻找的头和尾,以及中间的量,不断迭代找出最终答案;
代码如下
int Binary_Search(int a[], int n, int key)
{
int low, high, mid;
low = 1; /*定义最底下标为记录首位*/
high = n; /*定义最高下标为记录末位*/
while (low <= high)
{
mid = (low + high) / 2; /*折半*/
if (key < a[mid])
high = mid - 1;
else if (key > a[mid])
low = mid + 1;
else
return mid;
}
return -1; // 没找到
}
3.二分的快速用法
1.upper_bound: upper_bound(begin,end,num) 会从数组的 begin 位置到 end−1 位置二分查找第一个大于 num 的数字。
注意:这个返回值是地址,若是要找到这个a[pos],则,pos为upperbound减去寻找的数组:
#include<bits/stdc++.h>
using namespace std;
int main(){
int num[6]={1,2,4,7,15,34};
sort(num, num + 6); //按从小到大排序
int pos = upper_bound(num, num + 6, 7) - num; //返回数组中第一个大于被查数的值
cout << pos << " " << num[pos] << endl;
return 0;
}
注意,若是找不到,则会返回end。
二、二分答案
二分答案的思想
二分答案就是对最终答案的值进行二分,具体做法就是每次取一个中间答案,把答案作为已知条件, 判断根据当前答案是否满足题意, 根据判断结果再将区间缩小。**
写法和二分查找基本相同, 只不过要判断的东西比较复杂, 一般写法是通过写一个 check 函数来实现。
二分答案的技巧
二分答案通常是在寻找“合法”与“不合法”的边界,进一步说,是在寻找“刚好合法”的那个位置。
说白了,就是看这个答案会怎么影响已知量,已知量会偏大吗还是会偏小,从而确定这个答案怎么样
二分离不开单调性,我们做这类题目最重要的就是要找到题目中的某个与“合法性”有单调关系的量。(意思同上)
单调关系通常可以表现为: A 越大,越合法, A 越小,越不合法。在题目中总结出这种单调关系,十分有助于进一步思考。
上题目来康康,最简单的:
切木头
有n个木棍,长度不等,现在要将他们切成同等长度的木棍m个,并且每段的长度都为整数。问这m根木棍最长能有多长?
如果分不出来,输出0。
输入格式
第一行2个数:n, m中间用空格分隔(1 <= n <= 100000, 1 <= m <= 10^9) 后面n行:每行1个数,对应木棍的长度(1 <= Li <= 10^9)。
输出格式
输出一个整数,对应木棍的长度。
输入样例
3 10
15
25
12
输出样例
5
#include <bits/stdc++.h>
using namespace std;
int n;
long long a[100005];
long long m;
long long head=0;
long long ed=INT_MIN;
long long find(long long x){
long long cnt=0;
for(int i=1;i<=n;i++){
cnt+=a[i]/x;
}
return cnt;
}
int main(){//若ans太大,则m偏小,ans小则m偏大,
//要找m刚刚好的ans最大值 ,这就是单调性
cin >> n>> m;
if(n==m&&n==1){
cout<<"1";
return 0;
}
for(int i=1;i<=n;i++){
cin>>a[i];
ed=max(ed,a[i]);
}
if(ed==0){
cout<<0;
return 0;
}
if(m==1){
cout<<ed;
return 0;
}
//end不可能超过最大的a[i],否则一段也切不出来.
while(head+1<ed){//加一保证找的全
long long mid=(head+ed)/2;
long long mfind=find(mid);
if(mfind>=m){
head=mid;//因为找的是最大的满足值,
//所以偏小的不管是否刚好为m,都应该
//继续增大可能ans,
}
else{
ed=mid;
}
}
cout<<head;
}
** 最重要的一点**
1.看找的是最大值还是最小值,从而确定二分答案中=和>放在一起还是和<放在一起
2.为了保证搜索充分,head与end要在写二分答案之前找初始值(head=min-1;end=max+1),同时head+1<end才保证能顾到所有结果。
本文作者:linghusama
本文链接:https://www.cnblogs.com/linghusama/p/17303486.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步