📜  通过精确删除k个子数组以使数组成为素数来最大化数组的大小

📅  最后修改于: 2021-04-29 13:08:42             🧑  作者: Mango

给定一个由n个正整数和一个非负整数K组成的数组arr [] 。任务是从阵列中精确删除K个子阵列,以使该阵列中的所有其余元素均为质数,并且剩余阵列的大小最大。

例子:

一种简单的方法是在所有需要花费O(N 2 )时间复杂度的子阵列中进行搜索,然后跟踪特定子阵列长度中素数或合成数的数量。
一种有效的方法是跟踪两个连续复合材料之间的质数个数。

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

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

  1. 如果k为0并且数组中有复合整数,则这是不可能的情况。
  2. 如果k大于或等于合成数,则可以删除所有合成整数和多余的素数以等于值k。这些子数组的大小均为1,这为我们提供了最佳答案。
  3. 如果k小于复合整数,则我们必须删除那些包含所有复合且这些子数组中没有素数的子数组。

下面是上述方法的实现:

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


输出:
4