题目链接:3770. 可表示为连续质数和的最大质数(中等)
算法原理:
解法:前缀和+埃氏筛
击败33.69%
时间复杂度O(NLogLogN)
①边界处理:若 n=1,直接返回 0
②埃氏筛标记质数:初始化布尔数组标记 0~n 是否为质数,筛除所有非质数
③收集质数:遍历数组提取所有≤n 的质数,存入列表
④计算前缀和并截断:生成质数前缀和数组,和超过 n 时截断数组
⑤逆序查找:从前缀和数组末尾逆序找第一个是质数的和,无则返回 0
Java代码:
java
class Solution {
public int largestPrime(int n) {
if(n==1) return 0;
//核心优化:用埃氏筛标记质数,替代islegal和HashSet
boolean[] isPrime=new boolean[n+1];
for(int i=2;i<=n;i++) isPrime[i]=true;//先默认所有数都是质数
for(int i=2;i*i<=n;i++){
if(isPrime[i]){
//如果i是质数,那么i的所有倍数都不是质数
for(int j=i*i;j<=n;j+=i)
isPrime[j]=false;
}
}
List<Integer> prime=new ArrayList<>();
for(int i=2;i<=n;i++)
if(isPrime[i])
prime.add(i);
int[] sum=new int[prime.size()];
if(prime.isEmpty()) return 0;
sum[0]=prime.get(0);
if(sum[0]>n) return 0;
for(int i=1;i<prime.size();i++){
sum[i]=sum[i-1]+prime.get(i);
if(sum[i]>n){
//及时截断
sum=Arrays.copyOf(sum,i);
break;
}
}
for(int i=sum.length-1;i>=0;i--)
if(isPrime[sum[i]]) return sum[i];
return 0;
}
}