算法初步——二分 + two pointers B1030/A1085完美数列 (使用upper_bound函数 和 自己构建二分函数 )

二重循环枚举

#include <bits/stdc++.h>
#include<math.h>
#include <string>
using namespace std;
const int MAX_LEN = 100005;
bool cmp(int a,int b){
    return a<b;
}
int main(){
    int n;
    cin>>n;
    int temp[n];
    for(int i=0;i<n;++i){
        temp[i] = 0;
    }
    int p;
    //cin>>n;
    cin>>p;
    for(int i=0;i<n;++i){
        cin>>temp[i];
    }
    sort(temp,temp+n,cmp);
    int result[n];
    for(int i=0;i<n;++i){
        result[i] = n-i;
        /*for(int j=n-1;j>=0 && j>=i;--j){
            if(temp[i] * p > temp[j]){
                result[i]--;
            }
        }*/
        for(int j=i;j<n;++j){
            if(temp[i] * p >= temp[j]){
                continue;
            }else{
                result[i]--;
            }
        }
    }
    int max = 0;
    for(int i =0;i<n;++i){
        if(result[i] > max){
            max = result[i];
        }
    }
    cout<<max<<endl;
    //sort(result,result+n,cmp);
    //cout<<result[n-1]<<endl;
    /*int count = n-1;
    for(int i =n-1;i>=0;--i){
        if(temp[0] * p < temp[i]){
            count--;
        }
    }
    cout<<count+1<<endl;*/
    //int count = 0;
    /*for(int i =0;i<n;++i){
        for(int j=n-1;j>=0;--j){
            if(temp[i] * p < temp[j]){
                count
            }
        }
    }*/
    system("pause");
    return 0;
} 

最后一个错误用例,原因是 temp[i] * p 有可能超过 int 范围,应该用 long long 型存储!

如果强制进行O(n平方)的二重循环枚举,那么根据题目的数据范围,肯定会超时的。这里有两种方法来解决这个问题。

二分查找和 two pointers。

解法1:

二分查找(自己构建二分函数)

#include <bits/stdc++.h>
#include<math.h>
#include <string>
using namespace std;
const int MAX_LEN = 100005;
bool cmp(int a,int b){
    return a<b;
}
int n,p,a[MAX_LEN];
int binarySearch(int i,long long x){
    if(a[n-1] <= x) return n;
    int l = i+1,r = n-1,mid;
    while(l < r){
        mid = (l+r)/2;
        if(a[mid] <= x){
            l = mid + 1;
        }else{
            r = mid;
        }
    }
    return l;
}
int main(){
    scanf("%d%d",&n,&p);
    for(int i =0;i<n;++i){
        scanf("%d",&a[i]);
    }
    sort(a,a+n);//递增顺序
    int ans = 1;//最大长度,初值为1
    for(int i =0;i<n;++i){
        //在a[i+1]-a[n-1]中查找第一个超过a[i]*p的数,返回其位置给j
        int j = binarySearch(i,(long long)a[i] * p);
        ans = max(ans,j-i);
    }
    cout<<ans<<endl;
    system("pause");
    return 0;
} 

(2)使用upper_bound函数

#include <bits/stdc++.h>
#include<math.h>
#include <string>
using namespace std;
const int MAX_LEN = 100005;
bool cmp(int a,int b){
    return a<b;
}
int n,p,a[MAX_LEN];
int main(){
    scanf("%d%d",&n,&p);
    for(int i =0;i<n;++i){
        scanf("%d",&a[i]);
    }
    sort(a,a+n);//递增顺序
    int ans = 1;//最大长度,初值为1
    for(int i =0;i<n;++i){
        //在a[i+1]-a[n-1]中查找第一个超过a[i]*p的数,返回其位置给j
        int j = upper_bound(a+i+1,a+n,(long long)a[i] * p) - a;
        ans = max(ans,j-i);
    }
    cout<<ans<<endl;
    system("pause");
    return 0;
} 

two pointers 解法:

#include <bits/stdc++.h>
#include<math.h>
#include <string>
using namespace std;
const int MAX_LEN = 100005;
/*bool cmp(int a,int b){
    return a<b;
}*/
int n,p,a[MAX_LEN];
int main(){
    scanf("%d%d",&n,&p);
    for(int i =0;i<n;++i){
        scanf("%d",&a[i]);
    }
    sort(a,a+n);//递增顺序
    int i = 0,j=0,count = 1;
    while(i<n && j<n){
        //j不断右移,直到恰好不满足条件
        while(j < n && a[j] <= (long long)a[i] * p){
            count = max(count,j - i + 1);//更新计数器count
            j++; 
        }
        i++;//i右移一位 
    }
    cout<<count<<endl; 
    system("pause");
    return 0;
} 
原文地址:https://www.cnblogs.com/JasonPeng1/p/12185714.html