题意:
给定正整数数组A和一个正整数X,设A的长度为N,数组中的元素依次为A[0]~A[N - 1]。
现要挑选出符合以下条件的所有整数对(l, r):
存在至少X个不同的质数,每个质数都可以整除A[l]~A[r]之间的每一个数(A[l], A[l + 1], A[l + 2], ... A[r])。
方法一:
现要挑选出符合以下条件的所有整数对(l, r):
存在至少X个不同的质数,每个质数都可以整除A[l]~A[r]之间的每一个数(A[l], A[l + 1], A[l + 2], ... A[r])。
现在定义一个整数对(l, r)的长度为r - l + 1,找出长度第K大的整数对长度是多少。
如果符合条件的数对不足K个,那么返回-1。
暴力模拟
思路:先打表,获取素数表。
再用两重循环,得到一个区间;
并在这个区间里去遍历满足条件的素数,并统计素数的数量;
如果该区间内素数的数量满足,则将该区间的长度存储到长度数组;
最后从大到小排序,返回第K大的长度。
class Solution { public: static const int N=1e7+5; bool isPrime[N];//判断是否为素数 vector<int> prime;//存储素数 int GetKthLength(vector<int>& A, int X, int K) { int n=A.size(); getPrime();//获取素数表 vector<int> res; for(int i=0;i<n;i++){//遍历每个区间 for(int j=i;j<n;j++){ if(judge(i,j,A,X)){//如果满足,将区间长度加入队列 res.push_back(j-i+1); } } } sort(res.begin(),res.end(),greater<int>());//将区间长度从大到小排序 return res.size()<K?-1:res[K-1];//选择第K大长度 } int judge(int l,int r,vector<int> A,int num){ int ma=0;//取[l,r]的最大值 for(int i=l;i<=r;i++) ma=max(ma,A[i]); for(int i=0;prime[i]<=ma;i++){//遍历素数表,判断该素数是否可行 int flag=0; for(int j=l;j<=r;j++){ if(A[j]%prime[i]!=0){//不能整除,则这个素数不满足,舍弃 flag=1; break; } } if(flag==0) num--; if(num==0) return 1; } return 0; } void getPrime(){//线性筛素数O(n) int num=0;//素数的个数 memset(isPrime,true,sizeof(isPrime)); for(int i=2;i<=N;i++){ if(isPrime[i]){ prime.push_back(i); num++; } for(int j=0;j<num&&i*prime[j]<=N;j++){ isPrime[i*prime[j]]=false; if(i%prime[j]==0) break; } } } };
时间复杂度:空间复杂度:
方法二:
优化
思路:对于一个区间的数值,要求区间的每个数都要整除一个素数。
那么我们可以获取这个区间的最小值,
以最小值作为临界点,是素数小于等于最小值。这样可以优化遍历素数的个数。
class Solution { public: static const int N=1e7+5; bool isPrime[N];//判断是否为素数 vector<int> prime;//存储素数 int GetKthLength(vector<int>& A, int X, int K) { int n=A.size(); getPrime();//获取素数表 vector<int> res; for(int i=0;i<n;i++){//遍历每个区间 for(int j=i;j<n;j++){ if(judge(i,j,A,X)){//如果满足,将区间长度加入队列 res.push_back(j-i+1); } } } sort(res.begin(),res.end(),greater<int>());//将区间长度从大到小排序 return res.size()<K?-1:res[K-1];//选择第K大长度 } int judge(int l,int r,vector<int> A,int num){ int mi=N;//取[l,r]区间的最小值 for(int i=l;i<=r;i++){ mi=min(mi,A[i]); } for(int i=0;prime[i]<=mi;i++){//遍历素数表,判断该素数是否可行 int flag=0; for(int j=l;j<=r;j++){ if(A[j]%prime[i]!=0){//不能整除,则这个素数不满足,舍弃 flag=1; break; } } if(flag==0) num--; if(num==0) return 1; } return 0; } void getPrime(){//线性筛素数O(n) int num=0;//素数的个数 memset(isPrime,true,sizeof(isPrime)); for(int i=2;i<=N;i++){ if(isPrime[i]){ prime.push_back(i); num++; } for(int j=0;j<num&&i*prime[j]<=N;j++){ isPrime[i*prime[j]]=false; if(i%prime[j]==0) break; } } } };
时间复杂度:空间复杂度: