📜  仅具有K个不同素数的最长子数组的长度

📅  最后修改于: 2021-04-27 05:12:53             🧑  作者: Mango

给定一个由N个正整数组成的数组arr [] 。任务是找到该数组中最长的子数组的长度,该子数组恰好包含K个不同的素数。如果不存在任何子数组,则打印“ -1”

例子:

天真的方法:想法是生成所有可能的子数组,并检查是否有最大长度的子数组包含K个不同的素数。如果是,则打印该子数组的长度,否则打印“ -1”
时间复杂度: O(N 2 ),其中N是给定数组的长度。
空间复杂度: O(N)

高效的方法:想法是使用Eratosthenes筛子来计算素数,并使用“两指针技术”来解决上述问题。步骤如下:

  1. 使用Eratosthenes筛子预先计算给定数字是否为质数。
  2. 遍历给定数组中的素数。
  3. 直到K不为零,我们计算子数组中出现的不同素数,并将K减1。
  4. K变为负数时,请开始删除元素,直到当前子数组的第一个素数为止,因为此后可能会有更长的子数组。
  5. K0时,我们更新最大长度。
  6. 完成上述所有步骤后,打印最大长度。

下面是上述方法的实现:

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 ocurrence 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 ocurrence 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 ocurrence 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 ocurrence 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)