题意:
给定正整数数组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;
}
}
}
};
时间复杂度:
空间复杂度:![]()



京公网安备 11010502036488号