zoukankan      html  css  js  c++  java
  • 二分

    二分

    二分是一种思想,其不仅限于查找。其中查找是一个很典型的应用。个人对二分的理解:如果一个题目告诉你最大答案范围,即在那个范围里肯定存在一个答案,那么就可以用二分(查找很典型了吧,不过查找也可以找不到,最后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
    ",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
    ",r);
    	getchar();
    }
    
  • 相关阅读:
    JavaScript词法结构
    【python】类变量、实例变量
    把pandas dataframe转为list方法
    list 删除一个元素的三种做法--python
    Web.config中rewite 节点引起的500.19错误
    extjs让按钮可用或者不可用
    VS2010启动奔溃
    迟来的年终总结
    Nginx配置多个server
    RestSharp的简单用法
  • 原文地址:https://www.cnblogs.com/StungYep/p/12251761.html
Copyright © 2011-2022 走看看