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:
- Pre-calculate whether the given number is prime or not using the Sieve of Eratosthenes.
- Maintain the count of primes occurring in the given array while traversing it.
- Until K is not zero, we count the distinct prime occurring in the subarray and decrease K by 1.
- 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.
- When K is 0, we update the maximum length.
- Print the maximum length after all the above steps.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
bool isprime[2000010];
void SieveOfEratosthenes( int n)
{
memset (isprime, true , sizeof (isprime));
isprime[1] = false ;
for ( int p = 2; p * p <= n; p++) {
if (isprime[p] == true ) {
for ( int i = p * p; i <= n; i += p)
isprime[i] = false ;
}
}
}
int KDistinctPrime( int arr[], int n,
int k)
{
SieveOfEratosthenes(2000000);
map< int , int > cnt;
int result = -1;
for ( int i = 0, j = -1; i < n; ++i) {
int x = arr[i];
if (isprime[x]) {
if (++cnt[x] == 1) {
--k;
}
}
while (k < 0) {
x = arr[++j];
if (isprime[x]) {
if (--cnt[x] == 0) {
++k;
}
}
}
if (k == 0)
result = max(result, i - j);
}
return result;
}
int main( void )
{
int arr[] = { 1, 2, 3, 3, 4,
5, 6, 7, 8, 9 };
int K = 3;
int N = sizeof (arr) / sizeof (arr[0]);
cout << KDistinctPrime(arr, N, K);
return 0;
}
|
Java
import java.util.*;
import java.lang.*;
class GFG{
static boolean [] isprime = new boolean [ 2000010 ];
static void SieveOfEratosthenes( int n)
{
Arrays.fill(isprime, true );
isprime[ 1 ] = false ;
for ( int p = 2 ; p * p <= n; p++)
{
if (isprime[p] == true )
{
for ( int i = p * p; i <= n; i += p)
isprime[i] = false ;
}
}
}
static int KDistinctPrime( int arr[], int n,
int k)
{
SieveOfEratosthenes( 2000000 );
Map<Integer, Integer> cnt = new HashMap<>();
int result = - 1 ;
for ( int i = 0 , j = - 1 ; i < n; ++i)
{
int x = arr[i];
if (isprime[x])
{
cnt.put(x, cnt.getOrDefault(x, 0 ) + 1 );
if (cnt.get(x) == 1 )
{
--k;
}
}
while (k < 0 )
{
x = arr[++j];
if (isprime[x])
{
cnt.put(x, cnt.getOrDefault(x, 0 ) - 1 );
if (cnt.get(x) == 0 )
{
++k;
}
}
}
if (k == 0 )
result = Math.max(result, i - j);
}
return result;
}
public static void main (String[] args)
{
int arr[] = { 1 , 2 , 3 , 3 , 4 ,
5 , 6 , 7 , 8 , 9 };
int K = 3 ;
int N = arr.length;
System.out.println(KDistinctPrime(arr, N, K));
}
}
|
Python3
from collections import defaultdict
isprime = [ True ] * 2000010
def SieveOfEratosthenes(n):
isprime[ 1 ] = False
p = 2
while (p * p < = n):
if (isprime[p] = = True ):
for i in range (p * p, n + 1 , p):
isprime[i] = False
p + = 1
def KDistinctPrime(arr, n, k):
SieveOfEratosthenes( 2000000 )
cnt = defaultdict( lambda : 0 )
result = - 1
j = - 1
for i in range (n):
x = arr[i]
if (isprime[x]):
cnt[x] + = 1
if (cnt[x] = = 1 ):
k - = 1
while (k < 0 ):
j + = 1
x = arr[j]
if (isprime[x]):
cnt[x] - = 1
if (cnt[x] = = 0 ):
k + = 1
if (k = = 0 ):
result = max (result, i - j)
return result
arr = [ 1 , 2 , 3 , 3 , 4 ,
5 , 6 , 7 , 8 , 9 ]
K = 3
N = len (arr)
print (KDistinctPrime(arr, N, K))
|
C#
using System;
using System.Collections.Generic;
class GFG{
static bool [] isprime = new bool [2000010];
static void SieveOfEratosthenes( int n)
{
for ( int i = 0; i < isprime.Length; i++)
isprime[i] = true ;
isprime[1] = false ;
for ( int p = 2; p * p <= n; p++)
{
if (isprime[p] == true )
{
for ( int i = p * p; i <= n; i += p)
isprime[i] = false ;
}
}
}
static int KDistinctPrime( int []arr,
int n, int k)
{
SieveOfEratosthenes(2000000);
Dictionary< int ,
int > cnt = new Dictionary< int ,
int >();
int result = -1;
for ( int i = 0, j = -1; i < n; ++i)
{
int x = arr[i];
if (isprime[x])
{
if (cnt.ContainsKey(x))
cnt[x] = cnt[x] + 1;
else
cnt.Add(x, 1);
if (cnt[x] == 1)
{
--k;
}
}
while (k < 0)
{
x = arr[++j];
if (isprime[x])
{
if (cnt.ContainsKey(x))
cnt[x] = cnt[x] - 1;
else
cnt.Add(x, 0);
if (cnt[x] == 0)
{
++k;
}
}
}
if (k == 0)
result = Math.Max(result, i - j);
}
return result;
}
public static void Main(String[] args)
{
int []arr = {1, 2, 3, 3, 4,
5, 6, 7, 8, 9};
int K = 3;
int N = arr.Length;
Console.WriteLine(KDistinctPrime(arr, N, K));
}
}
|
Javascript
<script>
let isprime = new Array(2000010);
function SieveOfEratosthenes(n)
{
isprime.fill( true );
isprime[1] = false ;
for (let p = 2; p * p <= n; p++)
{
if (isprime[p] == true )
{
for (let i = p * p; i <= n; i += p)
isprime[i] = false ;
}
}
}
function KDistinctPrime(arr, n, k)
{
SieveOfEratosthenes(2000000);
let cnt = new Map();
let result = -1;
for (let i = 0, j = -1; i < n; ++i)
{
let x = arr[i];
if (isprime[x])
{
if (cnt.has(x))
cnt.set(x, cnt.get(x)+1)
else
cnt.set(x, 1);
if (cnt.get(x) == 1)
{
--k;
}
}
while (k < 0)
{
x = arr[++j];
if (isprime[x])
{
if (cnt.has(x))
cnt.set(x, cnt.get(x) - 1)
else
cnt.set(x, -1);
if (cnt.get(x) == 0)
{
++k;
}
}
}
if (k == 0)
result = Math.max(result, i - j);
}
return result;
}
let arr = [ 1, 2, 3, 3, 4, 5, 6, 7, 8, 9 ];
let K = 3;
let N = arr.length;
document.write(KDistinctPrime(arr, N, K));
</script>
|
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
- Initialize variables count, left, and max_len to 0
- Precompute all prime numbers up to the largest number in the array
- Iterate over each element in the array from left to right:
- If the current element is prime, increment the count of that prime in the count dictionary
- If the count of distinct primes in the count dictionary is greater than K, move the left pointer to the right until the count is less than or equal to K
- If the count of distinct primes in the count dictionary is equal to K, update max_len with the length of the current subarray (right – left + 1)
- Return max_len if it is greater than 0, Else return -1
C++
#include <bits/stdc++.h>
using namespace std;
bool isPrime( int n, const vector< int >& primes) {
for ( int p : primes) {
if (p * p > n)
break ;
if (n % p == 0)
return false ;
}
return n > 1;
}
int longestSubarrayWithKPrimes( const std::vector< int >& arr, int k) {
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);
}
std::unordered_map< int , int > count;
int left = 0;
int maxLen = -1;
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;
}
int main() {
vector< int > arr = {1, 2, 3, 4, 5, 6, 7, 8, 9};
int k = 1;
cout << longestSubarrayWithKPrimes(arr, k) << endl;
arr = {1, 2, 3, 3, 4, 5, 6, 7, 8, 9};
k = 3;
cout << longestSubarrayWithKPrimes(arr, k) << endl;
return 0;
}
|
Java
import java.util.*;
class GFG {
static boolean isPrime( int n, List<Integer> primes) {
for ( int p : primes) {
if (p * p > n)
break ;
if (n % p == 0 )
return false ;
}
return n > 1 ;
}
static int longestSubarrayWithKPrimes(List<Integer> arr, int k) {
int limit = Collections.max(arr);
List<Integer> primes = new ArrayList<>();
for ( int p = 2 ; p <= limit; p++) {
if (isPrime(p, primes))
primes.add(p);
}
Map<Integer, Integer> count = new HashMap<>();
int left = 0 ;
int maxLen = - 1 ;
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;
}
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));
arr = Arrays.asList( 1 , 2 , 3 , 3 , 4 , 5 , 6 , 7 , 8 , 9 );
k = 3 ;
System.out.println(longestSubarrayWithKPrimes(arr, k));
}
}
|
Python3
def is_prime(n, primes):
for p in primes:
if p * p > n:
break
if n % p = = 0 :
return False
return n > 1
def longest_subarray_with_k_primes(arr, k):
limit = max (arr)
primes = [p for p in range ( 2 , limit + 1 ) if is_prime(p, primes = [])]
count = {}
left = 0
max_len = - 1
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
arr = [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
k = 1
print (longest_subarray_with_k_primes(arr, k))
arr = [ 1 , 2 , 3 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
k = 3
print (longest_subarray_with_k_primes(arr, k))
|
C#
using System;
using System.Collections.Generic;
using System.Linq;
class GFG {
static bool IsPrime( int n, List< int > primes)
{
foreach ( int p in primes)
{
if (p * p > n)
break ;
if (n % p == 0)
return false ;
}
return n > 1;
}
static int LongestSubarrayWithKPrimes(List< int > arr,
int k)
{
int limit = arr.Max();
List< int > primes = new List< int >();
for ( int p = 2; p <= limit; p++) {
if (IsPrime(p, primes))
primes.Add(p);
}
Dictionary< int , int > count
= new Dictionary< int , int >();
int left = 0;
int maxLen = -1;
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;
}
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));
arr = new List< int >{ 1, 2, 3, 3, 4, 5, 6, 7, 8, 9 };
k = 3;
Console.WriteLine(LongestSubarrayWithKPrimes(
arr, k));
}
}
|
Javascript
function isPrime(n, primes) {
for (let p of primes) {
if (p * p > n)
break ;
if (n % p === 0)
return false ;
}
return n > 1;
}
function longestSubarrayWithKPrimes(arr, k) {
let limit = Math.max(...arr);
let primes = [];
for (let p = 2; p <= limit; p++) {
if (isPrime(p, primes))
primes.push(p);
}
let count = new Map();
let left = 0;
let maxLen = -1;
for (let right = 0; right < arr.length; right++) {
if (isPrime(arr[right], primes)) {
if (!count.has(arr[right])) {
count.set(arr[right], 0);
}
count.set(arr[right], count.get(arr[right]) + 1);
}
while (count.size > k) {
if (isPrime(arr[left], primes)) {
count.set(arr[left], count.get(arr[left]) - 1);
if (count.get(arr[left]) === 0)
count. delete (arr[left]);
}
left++;
}
if (count.size === k)
maxLen = Math.max(maxLen, right - left + 1);
}
return maxLen;
}
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let k = 1;
console.log(longestSubarrayWithKPrimes(arr, k));
arr = [1, 2, 3, 3, 4, 5, 6, 7, 8, 9];
k = 3;
console.log(longestSubarrayWithKPrimes(arr, k));
|
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.
Last Updated :
13 Sep, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...