LeetCode 2523题解:寻找区间内最小间隔质数对(C++代码)

一、题目解读
LeetCode 2523题要求在一个给定的整数区间 [left, right] 内,找到间隔最小的两个质数(即相邻质数的差值最小),并返回这对质数。若区间内不存在两个质数,则返回 [-1, -1]。题目考察质数筛选算法与区间内最优对查找的逻辑。
二、解题思路
采用经典埃拉托斯特尼筛法(Sieve of Eratosthenes)生成质数,并结合双指针思想寻找最小间隔对。核心思路分为三步:
1. 质数筛选:通过筛法标记 [0, right] 内所有非质数,构建质数列表。
2. 区间质数收集:从 left 开始遍历筛后数组,保留区间内的质数。
3. 最小间隔查找:遍历质数列表,用双指针比较相邻质数差值,记录最小间隔对。
三、解题步骤
1. 初始化筛法:创建布尔数组 is_prime,标记所有数默认为质数(true),排除 0 和 1。
2. 执行筛法:从 2 开始,若 i 是质数,则将 i 的倍数(i², i²+i,...)标记为非质数(false)。
3. 收集区间质数:从 max(2, left) 到 right 遍历,若 is_prime[i] 为 true,加入质数列表 primes。
4. 查找最小间隔:
若 primes 长度不足 2,直接返回 [-1, -1]。
用双指针 i 遍历 primes,计算相邻质数差 diff,更新最小差 min_diff 及对应质数对 result。
5. 返回结果:输出最小间隔质数对 result。
四、代码与注释
class Solution {
public:
vector<int> closestPrimes(int left, int right) {
// 使用埃拉托斯特尼筛法找出所有质数
vector<bool> is_prime(right + 1, true);
is_prime[0] = is_prime[1] = false; // 排除0和1
for (int i = 2; i * i <= right; ++i) { // 优化筛法边界:i² <= right
if (is_prime[i]) { // 若i是质数
for (int j = i * i; j <= right; j += i) { // 标记i的倍数
is_prime[j] = false;
}
}
}
// 收集区间内的所有质数
vector<int> primes;
for (int i = max(2, left); i <= right; ++i) {
if (is_prime[i]) {
primes.push_back(i); // 保留left及以上的质数
}
}
// 寻找最小间隔的质数对
if (primes.size() < 2) { // 质数不足2个,返回默认值
return {-1, -1};
}
int min_diff = INT_MAX; // 初始化最小差为最大值
vector<int> result;
for (int i = 1; i < primes.size(); ++i) {
int diff = primes[i] - primes[i-1];
if (diff < min_diff) { // 更新最小差及对应质数
min_diff = diff;
result = {primes[i-1], primes[i]};
}
}
return result;
}
};注释说明:
● 筛法优化:仅需遍历至 i * i <= right,避免重复标记。
● 区间处理:从 max(2, left) 开始收集质数,确保 left 可能为 1 时的正确性。
● 双指针查找:通过 primes[i] - primes[i-1] 直接计算相邻差,简化逻辑。
五、总结
本解法通过埃拉托斯特尼筛法高效预处理质数,再在区间内通过双指针线性查找最优解,时间复杂度 O(n log log n)(筛法) + O(n)(区间遍历),空间复杂度 O(n)(质数列表)。关键在于:
1. 筛法的边界优化:减少不必要的循环次数。
2. 区间处理的灵活性:确保 left 可能小于 2 时的兼容性。
3. 双指针的简洁性:避免嵌套循环,提升效率。
适用于对时间复杂度要求较高的场景,是解决区间质数查找问题的经典模板。
原创内容 转载请注明出处






