Open In App

Length of longest subarray having only K distinct Prime Numbers

Given an array arr[] consisting of N positive integers. The task is to find the length of the longest subarray of this array that contains exactly K distinct Prime Numbers. If there doesn’t exist any subarray, then print “-1”.

Examples:



Input: arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9}, K = 1
Output: 4
Explanation:
The subarray {6, 7, 8, 9} contains 4 elements and only one is prime (7). Therefore, the required length is 4.

Input: arr[] = {1, 2, 3, 3, 4, 5, 6, 7, 8, 9}, K = 3
Output: 8
Explanation: 
The subarray {3, 3, 4, 5, 6, 7, 8, 9} contains 8 elements and contains only 3 distinct primes(3, 5, and 7). Therefore, the required length is 8.



Naive Approach: The idea is to generate all possible subarray and check if any subarray with maximum length contains K distinct primes. If yes, then print that length of the subarray, else print “-1”.
Time Complexity: O(N2), where N is the length of the given array.
Space Complexity: O(N)

Efficient Approach: The idea is to use the Sieve of Eratosthenes to calculate the prime numbers and the Two Pointer Technique to solve the above problem. Below are the steps:

  1. Pre-calculate whether the given number is prime or not using the Sieve of Eratosthenes.
  2. Maintain the count of primes occurring in the given array while traversing it.
  3. Until K is not zero, we count the distinct prime occurring in the subarray and decrease K by 1.
  4. As K becomes negative, start deleting the elements till the first prime number of the current subarray as there might be a possibility of a longer subarray afterward.
  5. When K is 0, we update the maximum length.
  6. Print the maximum length after all the above steps.

Below is the implementation of the above approach:




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
bool isprime[2000010];
 
// Function to precalculate all the
// prime up to 10^6
void SieveOfEratosthenes(int n)
{
    // Initialize prime to true
    memset(isprime, true, sizeof(isprime));
 
    isprime[1] = false;
 
    // Iterate [2, sqrt(N)]
    for (int p = 2; p * p <= n; p++) {
 
        // If p is prime
        if (isprime[p] == true) {
 
            // Mark all multiple of p as true
            for (int i = p * p; i <= n; i += p)
                isprime[i] = false;
        }
    }
}
 
// Function that finds the length of
// longest subarray K distinct primes
int KDistinctPrime(int arr[], int n,
                   int k)
{
    // Precompute all prime up to 2*10^6
    SieveOfEratosthenes(2000000);
 
    // Keep track occurrence of prime
    map<int, int> cnt;
 
    // Initialize result to -1
    int result = -1;
 
    for (int i = 0, j = -1; i < n; ++i) {
 
        int x = arr[i];
 
        // If number is prime then
        // increment its count and
        // decrease k
        if (isprime[x]) {
 
            if (++cnt[x] == 1) {
 
                // Decrement K
                --k;
            }
        }
 
        // Remove required elements
        // till k become non-negative
        while (k < 0) {
 
            x = arr[++j];
            if (isprime[x]) {
 
                // Decrease count so
                // that it may appear
                // in another subarray
                // appearing after this
                // present subarray
                if (--cnt[x] == 0) {
 
                    // Increment K
                    ++k;
                }
            }
        }
 
        // Take the max value as
        // length of subarray
        if (k == 0)
            result = max(result, i - j);
    }
 
    // Return the final length
    return result;
}
 
// Driver Code
int main(void)
{
    // Given array arr[]
    int arr[] = { 1, 2, 3, 3, 4,
                  5, 6, 7, 8, 9 };
    int K = 3;
 
    int N = sizeof(arr) / sizeof(arr[0]);
 
    // Function Call
    cout << KDistinctPrime(arr, N, K);
    return 0;
}




// Java program for the above approach
import java.util.*;
import java.lang.*;
 
class GFG{
 
static boolean[] isprime = new boolean[2000010];
 
// Function to precalculate all the
// prime up to 10^6
static void SieveOfEratosthenes(int n)
{
     
    // Initialize prime to true
    Arrays.fill(isprime, true);
 
    isprime[1] = false;
 
    // Iterate [2, sqrt(N)]
    for(int p = 2; p * p <= n; p++)
    {
         
        // If p is prime
        if (isprime[p] == true)
        {
             
            // Mark all multiple of p as true
            for(int i = p * p; i <= n; i += p)
                isprime[i] = false;
        }
    }
}
 
// Function that finds the length of
// longest subarray K distinct primes
static int KDistinctPrime(int arr[], int n,
                                     int k)
{
     
    // Precompute all prime up to 2*10^6
    SieveOfEratosthenes(2000000);
 
    // Keep track occurrence of prime
    Map<Integer, Integer> cnt = new HashMap<>();
 
    // Initialize result to -1
    int result = -1;
 
    for(int i = 0, j = -1; i < n; ++i)
    {
        int x = arr[i];
 
        // If number is prime then
        // increment its count and
        // decrease k
        if (isprime[x])
        {
            cnt.put(x, cnt.getOrDefault(x, 0) + 1);
             
            if (cnt.get(x) == 1)
            {
                 
                // Decrement K
                --k;
            }
        }
 
        // Remove required elements
        // till k become non-negative
        while (k < 0)
        {
            x = arr[++j];
            if (isprime[x])
            {
                 
                // Decrease count so
                // that it may appear
                // in another subarray
                // appearing after this
                // present subarray
                cnt.put(x, cnt.getOrDefault(x, 0) - 1);
                if (cnt.get(x) == 0)
                {
                     
                    // Increment K
                    ++k;
                }
            }
        }
 
        // Take the max value as
        // length of subarray
        if (k == 0)
            result = Math.max(result, i - j);
    }
 
    // Return the final length
    return result;
}
 
// Driver Code
public static void main (String[] args)
{
     
    // Given array arr[]
    int arr[] = { 1, 2, 3, 3, 4,
                  5, 6, 7, 8, 9 };
    int K = 3;
     
    int N = arr.length;
     
    // Function call
    System.out.println(KDistinctPrime(arr, N, K));
}
}
 
// This code is contributed by offbeat




# Python3 program to implement
# the above approach
from collections import defaultdict
 
isprime = [True] * 2000010
 
# Function to precalculate all the
# prime up to 10^6
def SieveOfEratosthenes(n):
 
    isprime[1] = False
 
    # Iterate [2, sqrt(N)]
    p = 2
    while(p * p <= n):
 
        # If p is prime
        if(isprime[p] == True):
 
            # Mark all multiple of p as true
            for i in range(p * p, n + 1, p):
                isprime[i] = False
 
        p += 1
 
# Function that finds the length of
# longest subarray K distinct primes
def KDistinctPrime(arr, n, k):
 
    # Precompute all prime up to 2*10^6
    SieveOfEratosthenes(2000000)
 
    # Keep track occurrence of prime
    cnt = defaultdict(lambda : 0)
 
    # Initialize result to -1
    result = -1
 
    j = -1
 
    for i in range(n):
        x = arr[i]
 
        # If number is prime then
        # increment its count and
        # decrease k
        if(isprime[x]):
            cnt[x] += 1
 
            if(cnt[x] == 1):
 
                # Decrement K
                k -= 1
 
    # Remove required elements
    # till k become non-negative
    while(k < 0):
        j += 1
        x = arr[j]
         
        if(isprime[x]):
 
            # Decrease count so
            # that it may appear
            # in another subarray
            # appearing after this
            # present subarray
            cnt[x] -= 1
            if(cnt[x] == 0):
 
                # Increment K
                k += 1
 
        # Take the max value as
        # length of subarray
        if(k == 0):
            result = max(result, i - j)
 
    # Return the final length
    return result
 
# Driver Code
 
# Given array arr[]
arr = [ 1, 2, 3, 3, 4,
        5, 6, 7, 8, 9 ]
 
K = 3
 
N = len(arr)
 
# Function call
print(KDistinctPrime(arr, N, K))
 
# This code is contributed by Shivam Singh




// C# program for the above approach
using System;
using System.Collections.Generic;
class GFG{
static bool[] isprime = new bool[2000010];
 
// Function to precalculate all the
// prime up to 10^6
static void SieveOfEratosthenes(int n)
{   
    // Initialize prime to true
    for(int i = 0; i < isprime.Length; i++)
        isprime[i] = true;
    isprime[1] = false;
 
    // Iterate [2, sqrt(N)]
    for(int p = 2; p * p <= n; p++)
    {       
        // If p is prime
        if (isprime[p] == true)
        {           
            // Mark all multiple of p as true
            for(int i = p * p; i <= n; i += p)
                isprime[i] = false;
        }
    }
}
 
// Function that finds the length of
// longest subarray K distinct primes
static int KDistinctPrime(int []arr,
                          int n, int k)
{   
    // Precompute all prime up to 2*10^6
    SieveOfEratosthenes(2000000);
 
    // Keep track occurrence of prime
    Dictionary<int,
               int> cnt = new Dictionary<int,
                                         int>();
 
    // Initialize result to -1
    int result = -1;
 
    for(int i = 0, j = -1; i < n; ++i)
    {
        int x = arr[i];
 
        // If number is prime then
        // increment its count and
        // decrease k
        if (isprime[x])
        {
            if(cnt.ContainsKey(x))
                cnt[x] = cnt[x] + 1;
            else
                cnt.Add(x, 1);           
            if (cnt[x] == 1)
            {               
                // Decrement K
                --k;
            }
        }
 
        // Remove required elements
        // till k become non-negative
        while (k < 0)
        {
            x = arr[++j];
            if (isprime[x])
            {               
                // Decrease count so
                // that it may appear
                // in another subarray
                // appearing after this
                // present subarray
                if(cnt.ContainsKey(x))
                    cnt[x] = cnt[x] - 1;
                else
                    cnt.Add(x, 0);
                if (cnt[x] == 0)
                {                   
                    // Increment K
                    ++k;
                }
            }
        }
 
        // Take the max value as
        // length of subarray
        if (k == 0)
            result = Math.Max(result, i - j);
    }
 
    // Return the readonly length
    return result;
}
 
// Driver Code
public static void Main(String[] args)
{   
    // Given array []arr
    int []arr = {1, 2, 3, 3, 4,
                 5, 6, 7, 8, 9};
    int K = 3;
     
    int N = arr.Length;
     
    // Function call
    Console.WriteLine(KDistinctPrime(arr, N, K));
}
}
 
// This code is contributed by 29AjayKumar




<script>
    // Javascript program for the above approach
     
    let isprime = new Array(2000010);
  
    // Function to precalculate all the
    // prime up to 10^6
    function SieveOfEratosthenes(n)
    {
 
        // Initialize prime to true
        isprime.fill(true);
 
        isprime[1] = false;
 
        // Iterate [2, sqrt(N)]
        for(let p = 2; p * p <= n; p++)
        {
 
            // If p is prime
            if (isprime[p] == true)
            {
 
                // Mark all multiple of p as true
                for(let i = p * p; i <= n; i += p)
                    isprime[i] = false;
            }
        }
    }
 
    // Function that finds the length of
    // longest subarray K distinct primes
    function KDistinctPrime(arr, n, k)
    {
 
        // Precompute all prime up to 2*10^6
        SieveOfEratosthenes(2000000);
 
        // Keep track occurrence of prime
        let cnt = new Map();
 
        // Initialize result to -1
        let result = -1;
 
        for(let i = 0, j = -1; i < n; ++i)
        {
            let x = arr[i];
 
            // If number is prime then
            // increment its count and
            // decrease k
            if (isprime[x])
            {
                if(cnt.has(x))
                    cnt.set(x, cnt.get(x)+1)
                else
                    cnt.set(x, 1);
 
                if (cnt.get(x) == 1)
                {
 
                    // Decrement K
                    --k;
                }
            }
 
            // Remove required elements
            // till k become non-negative
            while (k < 0)
            {
                x = arr[++j];
                if (isprime[x])
                {
 
                    // Decrease count so
                    // that it may appear
                    // in another subarray
                    // appearing after this
                    // present subarray
                    if(cnt.has(x))
                        cnt.set(x, cnt.get(x) - 1)
                    else
                        cnt.set(x, -1);
                    if (cnt.get(x) == 0)
                    {
 
                        // Increment K
                        ++k;
                    }
                }
            }
 
            // Take the max value as
            // length of subarray
            if (k == 0)
                result = Math.max(result, i - j);
        }
 
        // Return the final length
        return result;
    }
     
    // Given array arr[]
    let arr = [ 1, 2, 3, 3, 4, 5, 6, 7, 8, 9 ];
    let K = 3;
     
    let N = arr.length;
      
    // Function call
    document.write(KDistinctPrime(arr, N, K));
 
</script>

Output
8






Time Complexity: O(N*log(log(N))), where N is the maximum element in the given array. 
Auxiliary Space: O(N)

Another Method (sliding window approach)

The task is to find the length of the longest subarray of this array  can be found out using sliding window approach 

Algorithm




//C++ program for the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to check if N is prime or not
bool isPrime(int n, const vector<int>& primes) {
    // Check if n is prime using the
    // precomputed list of primes
    for (int p : primes) {
        if (p * p > n)
            break;
        if (n % p == 0)
            return false;
    }
    return n > 1;
}
 
// Function to find the longest subarray
// with K primes
int longestSubarrayWithKPrimes(const std::vector<int>& arr, int k) {
    // Precompute all primes up to
    // the largest number in the array
    int limit = *std::max_element(arr.begin(), arr.end());
    std::vector<int> primes;
    for (int p = 2; p <= limit; p++) {
        if (isPrime(p, primes))
            primes.push_back(p);
    }
 
    // Initialize variables
    std::unordered_map<int, int> count;
    int left = 0;
    int maxLen = -1;
 
    // Move the window to the right until
    // we find a window with K distinct primes
    for (int right = 0; right < arr.size(); right++) {
        if (isPrime(arr[right], primes))
            count[arr[right]] += 1;
        while (count.size() > k) {
            if (isPrime(arr[left], primes)) {
                count[arr[left]] -= 1;
                if (count[arr[left]] == 0)
                    count.erase(arr[left]);
            }
            left++;
        }
        if (count.size() == k)
            maxLen = std::max(maxLen, right - left + 1);
    }
 
    return maxLen;
}
 
// Driver Code
int main() {
     
    vector<int> arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    int k = 1;
    cout << longestSubarrayWithKPrimes(arr, k) << endl;  // Output: 4
 
    arr = {1, 2, 3, 3, 4, 5, 6, 7, 8, 9};
    k = 3;
    cout << longestSubarrayWithKPrimes(arr, k) << endl;  // Output: 8
 
    return 0;
}
 
// This code is contributed by Utkarsh Kumar




//Java program for the above approach
import java.util.*;
 
class GFG {
    // Function to check if N is prime or not
    static boolean isPrime(int n, List<Integer> primes) {
        // Check if n is prime using the
        // precomputed list of primes
        for (int p : primes) {
            if (p * p > n)
                break;
            if (n % p == 0)
                return false;
        }
        return n > 1;
    }
 
    // Function to find the longest subarray
    // with K primes
    static int longestSubarrayWithKPrimes(List<Integer> arr, int k) {
        // Precompute all primes up to
        // the largest number in the array
        int limit = Collections.max(arr);
        List<Integer> primes = new ArrayList<>();
        for (int p = 2; p <= limit; p++) {
            if (isPrime(p, primes))
                primes.add(p);
        }
 
        // Initialize variables
        Map<Integer, Integer> count = new HashMap<>();
        int left = 0;
        int maxLen = -1;
 
        // Move the window to the right until
        // we find a window with K distinct primes
        for (int right = 0; right < arr.size(); right++) {
            if (isPrime(arr.get(right), primes))
                count.put(arr.get(right), count.getOrDefault(arr.get(right), 0) + 1);
            while (count.size() > k) {
                if (isPrime(arr.get(left), primes)) {
                    count.put(arr.get(left), count.get(arr.get(left)) - 1);
                    if (count.get(arr.get(left)) == 0)
                        count.remove(arr.get(left));
                }
                left++;
            }
            if (count.size() == k)
                maxLen = Math.max(maxLen, right - left + 1);
        }
 
        return maxLen;
    }
 
    // Driver Code
    public static void main(String[] args) {
        List<Integer> arr = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
        int k = 1;
        System.out.println(longestSubarrayWithKPrimes(arr, k)); // Output: 4
 
        arr = Arrays.asList(1, 2, 3, 3, 4, 5, 6, 7, 8, 9);
        k = 3;
        System.out.println(longestSubarrayWithKPrimes(arr, k)); // Output: 8
    }
}
 
// This code is contributed by Pushpesh Raj.




# Python program for the above approach
 
# Function to check if N is prime or not
def is_prime(n, primes):
    # Check if n is prime using the
    # precomputed list of primes
    for p in primes:
        if p*p > n:
            break
        if n % p == 0:
            return False
    return n > 1
 
# Function to find the longest subarray
# with K primes
def longest_subarray_with_k_primes(arr, k):
    # Precompute all primes up to
    # the largest number in the array
    limit = max(arr)
    primes = [p for p in range(2, limit+1) if is_prime(p, primes=[])]
 
    # Initialize variables
    count = {}
    left = 0
    max_len = -1
 
    # Move the window to the right until
    # we find a window with K distinct primes
    for right in range(len(arr)):
        if is_prime(arr[right], primes):
            count[arr[right]] = count.get(arr[right], 0) + 1
        while len(count) > k:
            if is_prime(arr[left], primes):
                count[arr[left]] -= 1
                if count[arr[left]] == 0:
                    del count[arr[left]]
            left += 1
        if len(count) == k:
            max_len = max(max_len, right-left+1)
 
    return max_len
 
# Driver Code
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
k = 1
print(longest_subarray_with_k_primes(arr, k))  # Output: 4
 
arr = [1, 2, 3, 3, 4, 5, 6, 7, 8, 9]
k = 3
print(longest_subarray_with_k_primes(arr, k))  # Output: 8




using System;
using System.Collections.Generic;
using System.Linq;
 
class GFG {
    // Function to check if N is prime or not
    static bool IsPrime(int n, List<int> primes)
    {
        // Check if n is prime using the
        // precomputed list of primes
        foreach(int p in primes)
        {
            if (p * p > n)
                break;
            if (n % p == 0)
                return false;
        }
        return n > 1;
    }
 
    // Function to find the longest subarray
    // with K primes
    static int LongestSubarrayWithKPrimes(List<int> arr,
                                          int k)
    {
        // Precompute all primes up to
        // the largest number in the array
        int limit = arr.Max();
        List<int> primes = new List<int>();
        for (int p = 2; p <= limit; p++) {
            if (IsPrime(p, primes))
                primes.Add(p);
        }
 
        // Initialize variables
        Dictionary<int, int> count
            = new Dictionary<int, int>();
        int left = 0;
        int maxLen = -1;
 
        // Move the window to the right until
        // we find a window with K distinct primes
        for (int right = 0; right < arr.Count; right++) {
            if (IsPrime(arr[right], primes))
                count[arr[right]]
                    = count.GetValueOrDefault(arr[right])
                      + 1;
            while (count.Count > k) {
                if (IsPrime(arr[left], primes)) {
                    count[arr[left]] -= 1;
                    if (count[arr[left]] == 0)
                        count.Remove(arr[left]);
                }
                left++;
            }
            if (count.Count == k)
                maxLen = Math.Max(maxLen, right - left + 1);
        }
 
        return maxLen;
    }
 
    // Driver Code
    static void Main()
    {
        List<int> arr
            = new List<int>{ 1, 2, 3, 4, 5, 6, 7, 8, 9 };
        int k = 1;
        Console.WriteLine(LongestSubarrayWithKPrimes(
            arr, k)); // Output: 4
 
        arr = new List<int>{ 1, 2, 3, 3, 4, 5, 6, 7, 8, 9 };
        k = 3;
        Console.WriteLine(LongestSubarrayWithKPrimes(
            arr, k)); // Output: 8
    }
}




// Function to check if N is prime or not
function isPrime(n, primes) {
    for (let p of primes) {
        if (p * p > n)
            break;
        if (n % p === 0)
            return false;
    }
    return n > 1;
}
 
// Function to find the longest subarray with K primes
function longestSubarrayWithKPrimes(arr, k) {
    let limit = Math.max(...arr); // Find the largest number in the array
    let primes = [];
     
    // Precompute prime numbers up to the limit
    for (let p = 2; p <= limit; p++) {
        if (isPrime(p, primes))
            primes.push(p);
    }
 
    let count = new Map(); // Map to keep track of occurrences of prime elements
    let left = 0; // Left pointer of the sliding window
    let maxLen = -1; // Length of the longest subarray with K primes
 
    for (let right = 0; right < arr.length; right++) {
        if (isPrime(arr[right], primes)) {
            if (!count.has(arr[right])) {
                count.set(arr[right], 0); // Initialize count for a new prime element
            }
            count.set(arr[right], count.get(arr[right]) + 1); // Increment count for the prime element
        }
 
        // Contract the window from the left until only K distinct primes are present
        while (count.size > k) {
            if (isPrime(arr[left], primes)) {
                count.set(arr[left], count.get(arr[left]) - 1); // Decrement count for the prime element
                if (count.get(arr[left]) === 0)
                    count.delete(arr[left]); // Remove element from the map if count becomes 0
            }
            left++; // Move the left pointer to contract the window
        }
 
        // Update the maxLen if the current window has K distinct primes
        if (count.size === k)
            maxLen = Math.max(maxLen, right - left + 1);
    }
 
    return maxLen;
}
 
// Driver Code
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let k = 1;
console.log(longestSubarrayWithKPrimes(arr, k));  // Output: 4
 
arr = [1, 2, 3, 3, 4, 5, 6, 7, 8, 9];
k = 3;
console.log(longestSubarrayWithKPrimes(arr, k));  // Output: 8

Output
4
8






Time Complexity: O(N * log(log(max(arr))) + N2), where N is the length of the input array and max(arr) is the maximum element in the array.
Space Complexity: O(max(arr)), due to the count dictionary used to store the count of each prime number in the subarray.


Article Tags :