Closest Prime Numbers in Range

medium math number theory sieve

Problem

Given two positive integers left and right, find primes num1 and num2 with left ≤ num1 < num2 ≤ right such that num2 − num1 is the minimum over all valid prime pairs. Return [num1, num2]; on ties pick the smallest num1. If no such pair exists, return [-1, -1].

Inputleft = 10, right = 19
Output[11, 13]
Primes in range are 11, 13, 17, 19. The smallest gap is 2, met by [11,13] and [17,19]; since 11 < 17 we return [11,13].

def closestPrimes(left, right):
    # Sieve of Eratosthenes: mark primes up to right
    is_prime = [True] * (right + 1)
    is_prime[0] = False
    if right >= 1:
        is_prime[1] = False
    i = 2
    while i * i <= right:
        if is_prime[i]:
            for j in range(i * i, right + 1, i):
                is_prime[j] = False
        i += 1
    # scan consecutive primes in [left, right] for the smallest gap
    prev = -1
    ans = [-1, -1]
    best = float("inf")
    for n in range(left, right + 1):
        if is_prime[n]:
            if prev != -1 and n - prev < best:
                best = n - prev
                ans = [prev, n]
            prev = n
    return ans
function closestPrimes(left, right) {
  // Sieve of Eratosthenes: mark primes up to right
  const isPrime = new Array(right + 1).fill(true);
  isPrime[0] = false;
  if (right >= 1) isPrime[1] = false;
  for (let i = 2; i * i <= right; i++) {
    if (isPrime[i]) {
      for (let j = i * i; j <= right; j += i) isPrime[j] = false;
    }
  }
  // scan consecutive primes in [left, right] for the smallest gap
  let prev = -1, best = Infinity;
  let ans = [-1, -1];
  for (let n = left; n <= right; n++) {
    if (isPrime[n]) {
      if (prev !== -1 && n - prev < best) {
        best = n - prev;
        ans = [prev, n];
      }
      prev = n;
    }
  }
  return ans;
}
int[] closestPrimes(int left, int right) {
    // Sieve of Eratosthenes: mark primes up to right
    boolean[] isPrime = new boolean[right + 1];
    Arrays.fill(isPrime, true);
    isPrime[0] = false;
    if (right >= 1) isPrime[1] = false;
    for (int i = 2; i * i <= right; i++) {
        if (isPrime[i]) {
            for (int j = i * i; j <= right; j += i) isPrime[j] = false;
        }
    }
    // scan consecutive primes in [left, right] for the smallest gap
    int prev = -1, best = Integer.MAX_VALUE;
    int[] ans = {-1, -1};
    for (int n = left; n <= right; n++) {
        if (isPrime[n]) {
            if (prev != -1 && n - prev < best) {
                best = n - prev;
                ans = new int[]{prev, n};
            }
            prev = n;
        }
    }
    return ans;
}
vector<int> closestPrimes(int left, int right) {
    // Sieve of Eratosthenes: mark primes up to right
    vector<bool> isPrime(right + 1, true);
    isPrime[0] = false;
    if (right >= 1) isPrime[1] = false;
    for (int i = 2; i * i <= right; i++) {
        if (isPrime[i]) {
            for (int j = i * i; j <= right; j += i) isPrime[j] = false;
        }
    }
    // scan consecutive primes in [left, right] for the smallest gap
    int prev = -1, best = INT_MAX;
    vector<int> ans = {-1, -1};
    for (int n = left; n <= right; n++) {
        if (isPrime[n]) {
            if (prev != -1 && n - prev < best) {
                best = n - prev;
                ans = {prev, n};
            }
            prev = n;
        }
    }
    return ans;
}
Time: O(right · log log right) Space: O(right)