二分
二分是一种思想,其不仅限于查找。其中查找是一个很典型的应用。个人对二分的理解:如果一个题目告诉你最大答案范围,即在那个范围里肯定存在一个答案,那么就可以用二分(查找很典型了吧,不过查找也可以找不到,最后arr[mid]!=num to be find)。
二分查找是一种查找效率非常高的算法,时间复杂度为O(log2n)不过前提是数组提前排列好顺序,其实现代码如下:
1.二分递归版本
int binarysearch(int *arr,int key,int l,int r) { int mid=(r+l)>>1; if(l>r) return -1; else if(key==arr[mid]) return mid; else if(key>arr[mid]) return binarysearch(arr,key,mid+1,right); else if(key<arr[mid]) return binarysearch(arr,key,left,mid-1); return -1; }
2.二分非递归版本
int binarySearch1(int *a,int n,int target) { int l=1,r=n,mid; while(l<r) { mid=(l+r)>>1; if(a[mid]>=target) r=mid; else l=mid+1; } if(arr[l]==target) return l; return -1; }
【题意】:输入n(字符长度),k(最多关灯次数),字符串中1表示开灯,0表示关灯,问最少每次要关几盏灯。
思路:直接二分答案,答案肯定在1~n之内。看代码:
#include<bits/stdc++.h> using namespace std; const int maxn=5e5+10; char s[maxn]; int n,k,posr,posl; bool check(int x) { int start=posl; int cnt=0; while(start<=posr) { start+=x; cnt++; while(s[start]!='1') start++; } if(cnt>k) return 0; if(cnt<=k) return 1; } int main() { int T; scanf("%d",&T); while(T--) { scanf("%d %d",&n,&k); scanf("%s",s+1); posr=n,posl=1; while(s[posr]!='1') posr--; while(s[posl]!='1') posl++; int l,r,mid; l=1,r=n; mid=(l+n)>>1; while(l<r) //二分答案每次检验答案是否符合题意 { mid=(l+r)>>1; if(check(mid)) r=mid; else l=mid+1; } mid=(l+r)>>1; printf("%d\n",mid); } }
注意:整数上的二分条件为l=mid+1,r=mid
;而实数上的二分条件为:l=mid,r=mid
。
三分及其应用
这里的单峰函数是指有唯一一个极大值点,且峰值左右两边严格单调,这时可以选两个点将函数三分,show code:
#include <bits/stdc++.h> using namespace std; const double eps=1e-7; int n; double l,r,idx[20]; double f(double x) { double ans=0; for(int i=0;i<=n;++i) ans+=idx[i]*pow(x,n-i); return ans; } int main() { ios::sync_with_stdio(false); cin>>n>>l>>r; for(int i=0;i<=n;++i) cin>>idx[i]; while(r-l>eps) //注意退出循环的条件,一般高两个精度即可 { double mid=(l+r)/2; if(f(mid-eps)<f(mid+eps)) l=mid; else r=mid; } printf("%.5lf\n",r); getchar(); }
来源:https://www.cnblogs.com/StungYep/p/12251761.html