给定一个由N 个正整数组成的数组arr[] 。任务是找到这个数组的最长子数组的长度,该数组恰好包含K 个不同的素数。如果不存在任何子数组,则打印“-1” 。
例子:
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.
朴素的方法:这个想法是生成所有可能的子数组并检查最大长度的子数组是否包含K 个不同的素数。如果是,则打印子数组的该长度,否则打印“-1” 。
时间复杂度: O(N 2 ),其中 N 是给定数组的长度。
空间复杂度: O(N)
高效方法:思路是利用埃拉托色尼筛法计算素数和二指针技术来解决上述问题。以下是步骤:
- 使用埃拉托色尼筛法预先计算给定的数是否为素数。
- 在遍历给定数组时保持出现在给定数组中的素数计数。
- 直到K不为零,我们计算子数组中出现的不同素数并将K减 1。
- 当K变为负数时,开始删除元素直到当前子数组的第一个素数,因为之后可能会有更长的子数组。
- 当K为0 时,我们更新最大长度。
- 完成上述所有步骤后打印最大长度。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
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 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
// 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 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
# 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#
// 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 cnt = new Dictionary();
// 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
8
时间复杂度: O(N*log(log(N))),其中 N 是给定数组中的最大元素。
辅助空间: O(N)
如果您想与行业专家一起参加直播课程,请参阅Geeks Classes Live