📜  通过精确删除 k 个子数组使数组质数最大化数组的大小

📅  最后修改于: 2021-10-25 10:06:20             🧑  作者: Mango

给定一个由N 个正整数和一个非负整数K 组成的数组arr[] 。任务是从数组中精确删除K个子数组,使得数组的所有剩余元素都是素数,并且剩余数组的大小是最大的。

例子:

一种简单的方法是搜索所有需要O(N 2 )时间复杂度的子数组,然后跟踪特定长度子数组中的质数或复合数。

一种有效的方法是跟踪两个连续组合之间的素数数量。

  1. 预处理步骤:使用埃拉托色尼筛法将所有素数存储在素数数组中
  2. 计算向量 v 中所有合数的索引。
  3. 计算向量 diff 中上述向量的两个连续索引之间的距离,因为这将存储任何两个连续组合之间的素数数量。
  4. 对这个向量进行排序。排序后,我们得到包含最少素数到最多素数的子数组。
  5. 计算这个向量的前缀和。现在 diff 的每个索引表示 k 值,diff 中的值表示删除 k 个子数组时要删除的素数。第 0 个索引表示小于 v 大小的最大 k,第 1 个索引表示第二大 k,依此类推。所以,从前缀和向量中,我们直接得到要删除的素数的个数。

执行上述步骤后,我们的解决方案取决于三种情况:

  1. 如果 k 为 0 并且数组中存在合整数,则这是不可能的情况。
  2. 如果 k 大于或等于没有合数,那么我们可以删除全合整数和额外的素数来等于值 k。这些所有子数组的大小为 1,这为我们提供了最佳答案。
  3. 如果 k 小于合整数的 no,那么我们必须删除那些包含所有合整数的子数组,并且没有落入这些子数组的素数。

下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
const int N = 1e7 + 5;
bool prime[N];
 
// Sieve of Eratosthenes
void seive()
{
    for (int i = 2; i < N; i++) {
        if (!prime[i]) {
            for (int j = i + i; j < N; j += i) {
                prime[j] = 1;
            }
        }
    }
    prime[1] = 1;
}
 
// Function to return the size
// of the maximized array
int maxSizeArr(int* arr, int n, int k)
{
    vector v, diff;
 
    // Insert the indices of composite numbers
    for (int i = 0; i < n; i++) {
        if (prime[arr[i]])
            v.push_back(i);
    }
 
    // Compute the number of prime between
    // two consecutive composite
    for (int i = 1; i < v.size(); i++) {
        diff.push_back(v[i] - v[i - 1] - 1);
    }
 
    // Sort the diff vector
    sort(diff.begin(), diff.end());
 
    // Compute the prefix sum of diff vector
    for (int i = 1; i < diff.size(); i++) {
        diff[i] += diff[i - 1];
    }
 
    // Impossible case
    if (k > n || (k == 0 && v.size())) {
        return -1;
    }
 
    // Delete sub-arrays of length 1
    else if (v.size() <= k) {
        return (n - k);
    }
 
    // Find the number of primes to be deleted
    // when deleting the sub-arrays
    else if (v.size() > k) {
        int tt = v.size() - k;
        int sum = 0;
        sum += diff[tt - 1];
        int res = n - (v.size() + sum);
        return res;
    }
}
 
// Driver code
int main()
{
    seive();
    int arr[] = { 2, 4, 2, 2, 4, 2, 4, 2 };
    int n = sizeof(arr) / sizeof(arr[0]);
    int k = 2;
    cout << maxSizeArr(arr, n, k);
 
    return 0;
}


Java
// Java implementation of the approach
import java.util.*;
 
class GFG
{
 
static int N = 10000005;
static int []prime = new int[N];
 
// Sieve of Eratosthenes
static void seive()
{
    for (int i = 2; i < N; i++)
    {
        if (prime[i] == 0)
        {
            for (int j = i + i; j < N; j += i)
            {
                prime[j] = 1;
            }
        }
    }
    prime[1] = 1;
}
 
// Function to return the size
// of the maximized array
static int maxSizeArr(int arr[], int n, int k)
{
    ArrayList v = new ArrayList();
    ArrayList diff = new ArrayList();
 
    // Insert the indices of composite numbers
    int num = 0;
    for (int i = 0; i < n; i++)
    {
        if (prime[arr[i]] == 1)
        {
            v.add(i);
        }
    }
 
    // Compute the number of prime between
    // two consecutive composite
    num = 0;
    for (int i = 1; i < v.size(); i++)
    {
        diff.add(v.get(i) - v.get(i - 1) - 1);
    }
 
    // Sort the diff vector
    Collections.sort(diff);
 
    // Compute the prefix sum of diff vector
    for (int i = 1; i < diff.size(); i++)
    {
        diff.set(i, diff.get(i) + diff.get(i - 1));
    }
 
    // Impossible case
    if (k > n || (k == 0 && v.size() > 0))
    {
        return -1;
    }
 
    // Delete sub-arrays of length 1
    else if (v.size() <= k)
    {
        return (n - k);
    }
 
    // Find the number of primes to be deleted
    // when deleting the sub-arrays
    else if (v.size() > k)
    {
        int tt = v.size() - k;
        int sum = 0;
        sum += diff.get(tt - 1);
        int res = n - (v.size() + sum);
        return res;
    }
    return 1;
}
     
// Driver code
public static void main(String []args)
{
    seive();
    int []arr = { 2, 4, 2, 2, 4, 2, 4, 2 };
    int n = arr.length;
    int k = 2;
    System.out.println(maxSizeArr(arr, n, k));
}
}
 
// This code is contributed by Surendra_Gangwar


Python3
# Python implementation of above approach
 
N = 10000005
prime = [False]*N
 
# Sieve of Eratosthenes
def seive():
    for i in range(2,N):
        if not prime[i]:
            for j in range(i+1,N):
                prime[j] = True
     
    prime[1] = True
 
# Function to return the size
# of the maximized array
def maxSizeArr(arr, n, k):
    v, diff = [], []
 
    # Insert the indices of composite numbers
    for i in range(n):
        if prime[arr[i]]:
            v.append(i)
     
    # Compute the number of prime between
    # two consecutive composite
    for i in range(1, len(v)):
        diff.append(v[i] - v[i-1] -1)
     
    # Sort the diff vector
    diff.sort()
 
    # Compute the prefix sum of diff vector
    for i in range(1, len(diff)):
        diff[i] += diff[i-1]
     
    # Impossible case
    if k > n or (k == 0 and len(v)):
        return -1
     
    # Delete sub-arrays of length 1
    elif len(v) <= k:
        return (n-k)
     
    # Find the number of primes to be deleted
    # when deleting the sub-arrays
    elif len(v) > k:
        tt = len(v) - k
        s = 0
        s += diff[tt-1]
        res = n - (len(v) + s)
        return res
 
 
# Driver code
if __name__ == "__main__":
     
    seive()
 
    arr = [2, 4, 2, 2, 4, 2, 4, 2]
    n = len(arr)
    k = 2
 
    print(maxSizeArr(arr, n, k))
 
# This code is contributed by
# sanjeev2552


C#
// C# implementation of the approach
using System;
using System.Collections.Generic;
 
class GFG{
 
static int N = 1000005;
static int []prime = new int[N];
 
// Sieve of Eratosthenes
static void seive()
{
    for(int i = 2; i < N; i++)
    {
        if (prime[i] == 0)
        {
            for(int j = i + i;
                    j < N; j += i)
            {
                prime[j] = 1;
            }
        }
    }
    prime[1] = 1;
}
 
// Function to return the size
// of the maximized array
static int maxSizeArr(int []arr, int n,
                                 int k)
{
    List v = new List();
    List diff = new List();
 
    // Insert the indices of composite numbers
    //int num = 0;
     
    for(int i = 0; i < n; i++)
    {
        if (prime[arr[i]] == 1)
        {
            v.Add(i);
        }
    }
 
    // Compute the number of prime between
    // two consecutive composite
    //num = 0;
    for(int i = 1; i < v.Count; i++)
    {
        diff.Add(v[i] - v[i - 1] - 1);
    }
 
    // Sort the diff vector
    diff.Sort();
 
    // Compute the prefix sum of diff vector
    for(int i = 1; i < diff.Count; i++)
    {
        diff[i] = diff[i] + diff[i - 1];
    }
 
    // Impossible case
    if (k > n || (k == 0 && v.Count > 0))
    {
        return -1;
    }
 
    // Delete sub-arrays of length 1
    else if (v.Count <= k)
    {
        return (n - k);
    }
 
    // Find the number of primes to be deleted
    // when deleting the sub-arrays
    else if (v.Count > k)
    {
        int tt = v.Count - k;
        int sum = 0;
        sum += diff[tt - 1];
        int res = n - (v.Count + sum);
        return res;
    }
    return 1;
}
     
// Driver code
public static void Main(String []args)
{
    seive();
    int []arr = { 2, 4, 2, 2, 4, 2, 4, 2 };
    int n = arr.Length;
    int k = 2;
     
    Console.WriteLine(maxSizeArr(arr, n, k));
}
}
 
// This code is contributed by Amit Katiyar


Javascript


输出:
4

如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程学生竞争性编程现场课程