Open In App

Minimum operations required to remove an array

Improve
Improve
Like Article
Like
Save
Share
Report

Given an array of N integers where N is even. There are two kinds of operations allowed on the array. 

  1. Increase the value of any element A[i] by 1.
  2. If two adjacent elements in the array are consecutive prime number, delete both the element. That is, A[i] is a prime number and A[i+1] is the next prime number.

The task is to find the minimum number of operation required to remove all the element of the array.

Examples: 

Input  : arr[] = { 1, 2, 4, 3 } 
Output : 5
Minimum 5 operation are required.
1. Increase the 2nd element by 1
{ 1, 2, 4, 3 } -> { 1, 3, 4, 3 }
2. Increase the 3rd element by 1
{ 1, 3, 4, 3 } -> { 1, 3, 5, 3 }
3. Delete the 2nd and 3rd element
{ 1, 3, 5, 3 } -> { 1, 3 }
4. Increase the 1st element by 1
{ 1, 3 } -> { 2, 3 }
5. Delete the 1st and 2nd element
{ 2, 3 } -> { }

Input : arr[] = {10, 12}
Output : 3

To remove numbers, we must transform two numbers to two consecutive primes. How to compute the minimum cost of transforming two numbers a, b to two consecutive primes, where the cost is the number of incrementation of both numbers? 

We use sieve to precompute prime numbers and then find the first prime p not greater than a and the first greater than p using array.

Once we have computed two nearest prime numbers, we use Dynamic Programming to solve the problem. Let dp[i][j] be the minimum cost of clearing the subarray A[i, j]. If there are two numbers in the array, the answer is easy to find. Now, for N > 2, try any element at position k > i as a pair for A[i], such that there are even number of elements from A[i, j] between A[i] and A[k]. For a fixed k, the minimum cost of clearing A[i, j], i.e dp[i][j], equals dp[i + 1][k – 1] + dp[k + 1][j] + (cost of transforming A[i] and A[k] into consecutive primes). We can compute the answer by iterating over all possible k. 

Below is the implementation of above approach:

C++




// C++ program to count minimum operations
// required to remove an array
#include<bits/stdc++.h>
#define MAX 100005
using namespace std;
 
// Return the cost to convert two numbers into
// consecutive prime number.
int cost(int a, int b, int prev[], int nxt[])
{
    int sub = a + b;
 
    if (a <= b && prev[b-1] >= a)
        return nxt[b] + prev[b-1] - a - b;
 
    a = max(a, b);
    a = nxt[a];
    b = nxt[a + 1];
 
    return a + b - sub;
}
 
// Sieve to store next and previous prime
// to a number.
void sieve(int prev[], int nxt[])
{
    int pr[MAX] = { 0 };
 
    pr[1] = 1;
    for (int i = 2; i < MAX; i++)
    {
        if (pr[i])
            continue;
 
        for (int j = i*2; j < MAX; j += i)
            pr[j] = 1;
    }
 
    // Computing next prime each number.
    for (int i = MAX - 1; i; i--)
    {
        if (pr[i] == 0)
            nxt[i] = i;
        else
            nxt[i] = nxt[i+1];
    }
 
    // Computing previous prime each number.
    for (int i = 1; i < MAX; i++)
    {
        if (pr[i] == 0)
            prev[i] = i;
        else
            prev[i] = prev[i-1];
    }
}
 
// Return the minimum number of operation required.
int minOperation(int arr[], int nxt[], int prev[], int n)
{
    int dp[n + 5][n + 5] = { 0 };
 
    // For each index.
    for (int r = 0; r < n; r++)
    {
        // Each subarray.
        for (int l = r-1; l >= 0; l -= 2)
        {
            dp[l][r] = INT_MAX;
 
            for (int ad = l; ad < r; ad += 2)
                dp[l][r] = min(dp[l][r], dp[l][ad] +
                          dp[ad+1][r-1] +
                          cost(arr[ad], arr[r], prev, nxt));
        }
    }
 
    return dp[0][n - 1] + n/2;
}
 
// Driven Program
int main()
{
    int arr[] = { 1, 2, 4, 3 };
    int n = sizeof(arr)/sizeof(arr[0]);
 
    int nxt[MAX], prev[MAX];
    sieve(prev, nxt);
 
    cout << minOperation(arr, nxt, prev, n);
 
    return 0;
}


Java




// Java program to count minimum operations
// required to remove an array
class GFG
{
 
static final int MAX = 100005;
 
// Return the cost to convert two
// numbers into consecutive prime number.
static int cost(int a, int b,
                int prev[], int nxt[])
{
    int sub = a + b;
 
    if (a <= b && prev[b - 1] >= a)
    {
        return nxt[b] + prev[b - 1] - a - b;
    }
 
    a = Math.max(a, b);
    a = nxt[a];
    b = nxt[a + 1];
 
    return a + b - sub;
}
 
// Sieve to store next and previous
// prime to a number.
static void sieve(int prev[], int nxt[])
{
    int pr[] = new int[MAX];
 
    pr[1] = 1;
    for (int i = 2; i < MAX; i++)
    {
        if (pr[i] == 1)
        {
            continue;
        }
 
        for (int j = i * 2; j < MAX; j += i)
        {
            pr[j] = 1;
        }
    }
 
    // Computing next prime each number.
    for (int i = MAX - 2; i > 0; i--)
    {
        if (pr[i] == 0)
        {
            nxt[i] = i;
        }
        else
        {
            nxt[i] = nxt[i + 1];
        }
    }
 
    // Computing previous prime each number.
    for (int i = 1; i < MAX; i++)
    {
        if (pr[i] == 0)
        {
            prev[i] = i;
        }
        else
        {
            prev[i] = prev[i - 1];
        }
    }
}
 
// Return the minimum number
// of operation required.
static int minOperation(int arr[], int nxt[],
                        int prev[], int n)
{
    int dp[][] = new int[n + 5][n + 5];
 
    // For each index.
    for (int r = 0; r < n; r++)
    {
        // Each subarray.
        for (int l = r - 1; l >= 0; l -= 2)
        {
            dp[l][r] = Integer.MAX_VALUE;
 
            for (int ad = l; ad < r; ad += 2)
            {
                dp[l][r] = Math.min(dp[l][r], dp[l][ad] +
                                    dp[ad + 1][r - 1] +
                                    cost(arr[ad], arr[r],
                                            prev, nxt));
            }
        }
    }
 
    return dp[0][n - 1] + n / 2;
}
 
// Driver Code
public static void main(String args[])
{
    int arr[] = {1, 2, 4, 3};
    int n = arr.length;
 
    int nxt[] = new int[MAX], prev[] = new int[MAX];
    sieve(prev, nxt);
 
    System.out.println(minOperation(arr, nxt, prev, n));
}
}
 
// This code is contributed by 29AjayKumar


Python3




# Python 3 program to count minimum
# operations required to remove an array
MAX = 100005
INT_MAX = 10000000
 
# Return the cost to convert two numbers
# into consecutive prime number.
def cost(a, b, prev, nxt):
    sub = a + b
    if (a <= b and prev[b - 1] >= a):
        return nxt[b] + prev[b - 1] - a - b
 
    a = max(a, b)
    a = nxt[a]
    b = nxt[a + 1]
    return a + b - sub
 
# Sieve to store next and previous
# prime to a number.
def sieve(prev, nxt):
    pr = [0 for i in range(MAX)]
 
    pr[1] = 1
    for i in range(1, MAX):
        if (pr[i]):
            continue
        for j in range(i * 2, MAX, i):
            pr[j] = 1
 
    # Computing next prime each number.
    for i in range(MAX - 2, -1, -1):
        if (pr[i] == 0):
            nxt[i] = i
        else:
            nxt[i] = nxt[i + 1]
 
    # Computing previous prime each number.
    for i in range(1, MAX):
        if (pr[i] == 0):
            prev[i] = i
        else:
            prev[i] = prev[i - 1]
 
# Return the minimum number of
# operation required.
def minOperation(arr, nxt, prev, n):
    dp = [[0 for i in range(n + 5)]
             for i in range(n + 5)]
 
    # For each index.
    for r in range(n):
         
        # Each subarray.
        for l in range(r - 1, -1, -2):
            dp[l][r] = INT_MAX;
 
            for ad in range(l, r, 2):
                dp[l][r] = min(dp[l][r], dp[l][ad] +
                               dp[ad + 1][r - 1] +
                               cost(arr[ad], arr[r],
                                         prev, nxt))
    return dp[0][n - 1] + n // 2
 
# Driver Code
arr = [1, 2, 4, 3]
n = len(arr)
 
nxt = [0 for i in range(MAX)]
prev = [0 for i in range(MAX)]
sieve(prev, nxt)
print(minOperation(arr, nxt, prev, n))
 
# This code is contributed by sahishelangia


C#




// C# program to count minimum operations
// required to remove an array
using System;
class GFG
{
 
static int MAX = 100005;
 
// Return the cost to convert two
// numbers into consecutive prime number.
static int cost(int a, int b,
                int[] prev, int[] nxt)
{
    int sub = a + b;
 
    if (a <= b && prev[b - 1] >= a)
    {
        return nxt[b] + prev[b - 1] - a - b;
    }
 
    a = Math.Max(a, b);
    a = nxt[a];
    b = nxt[a + 1];
 
    return a + b - sub;
}
 
// Sieve to store next and previous
// prime to a number.
static void sieve(int[] prev, int[] nxt)
{
    int[] pr = new int[MAX];
 
    pr[1] = 1;
    for (int i = 2; i < MAX; i++)
    {
        if (pr[i] == 1)
        {
            continue;
        }
 
        for (int j = i * 2; j < MAX; j += i)
        {
            pr[j] = 1;
        }
    }
 
    // Computing next prime each number.
    for (int i = MAX - 2; i > 0; i--)
    {
        if (pr[i] == 0)
        {
            nxt[i] = i;
        }
        else
        {
            nxt[i] = nxt[i + 1];
        }
    }
 
    // Computing previous prime each number.
    for (int i = 1; i < MAX; i++)
    {
        if (pr[i] == 0)
        {
            prev[i] = i;
        }
        else
        {
            prev[i] = prev[i - 1];
        }
    }
}
 
// Return the minimum number
// of operation required.
static int minOperation(int[] arr, int[] nxt,
                        int[] prev, int n)
{
    int[,] dp = new int[n + 5, n + 5];
 
    // For each index.
    for (int r = 0; r < n; r++)
    {
        // Each subarray.
        for (int l = r - 1; l >= 0; l -= 2)
        {
            dp[l, r] = Int32.MaxValue;
 
            for (int ad = l; ad < r; ad += 2)
            {
                dp[l, r] = Math.Min(dp[l, r], dp[l, ad] +
                                    dp[ad + 1, r - 1] +
                                    cost(arr[ad], arr[r],
                                            prev, nxt));
            }
        }
    }
 
    return dp[0, n - 1] + n / 2;
}
 
// Driver Code
public static void Main()
{
    int[] arr = {1, 2, 4, 3};
    int n = arr.Length;
 
    int[] nxt = new int[MAX];
    int[] prev = new int[MAX];
    sieve(prev, nxt);
 
    Console.WriteLine(minOperation(arr, nxt, prev, n));
}
}
 
// This code is contributed by Mukul Singh


PHP




<?php
// PHP program to count minimum operations
// required to remove an array
 
$MAX = 100005;
  
// Return the cost to convert two numbers into
// consecutive prime number.
function cost($a, $b, &$prev, &$nxt)
{
    $sub = $a + $b;
  
    if ($a <= $b && $prev[$b-1] >= $a)
        return $nxt[$b] + $prev[$b-1] - $a - $b;
  
    $a = max($a, $b);
    $a = $nxt[$a];
    $b = $nxt[$a + 1];
  
    return $a + $b - $sub;
}
  
// Sieve to store next and previous prime
// to a number.
function sieve(&$prev, &$nxt)
{
    global $MAX;
    $pr = array_fill(0,$MAX,NULL);
  
    $pr[1] = 1;
    for ($i = 2; $i < $MAX; $i++)
    {
        if ($pr[$i])
            continue;
  
        for ($j = $i*2; $j < $MAX; $j += $i)
            $pr[$j] = 1;
    }
  
    // Computing next prime each number.
    for ($i = $MAX - 1; $i; $i--)
    {
        if ($pr[$i] == 0)
            $nxt[$i] = $i;
        else
            $nxt[$i] = $nxt[$i+1];
    }
  
    // Computing previous prime each number.
    for ($i = 1; $i < $MAX; $i++)
    {
        if ($pr[$i] == 0)
            $prev[$i] = $i;
        else
            $prev[$i] = $prev[$i-1];
    }
}
  
// Return the minimum number of operation required.
function minOperation(&$arr, &$nxt, &$prev, $n)
{
    global $MAX;
    $dp = array_fill(0,($n + 5),array_fill(0,($n + 5),NULL));
  
    // For each index.
    for ($r = 0; $r < $n; $r++)
    {
        // Each subarray.
        for ($l = $r-1; $l >= 0; $l -= 2)
        {
            $dp[$l][$r] = PHP_INT_MAX;
  
            for ($ad = $l; $ad < $r; $ad += 2)
                $dp[$l][$r] = min($dp[$l][$r], $dp[$l][$ad] +
                          $dp[$ad+1][$r-1] +
                          cost($arr[$ad], $arr[$r], $prev, $nxt));
        }
    }
  
    return $dp[0][$n - 1] + $n/2;
}
  
// Driven Program
 
$arr = array( 1, 2, 4, 3 );
$n = sizeof($arr)/sizeof($arr[0]);
 
$nxt = array_fill(0,$MAX,NULL);
$prev = array_fill(0,$MAX,NULL);
sieve($prev, $nxt);
 
echo minOperation($arr, $nxt, $prev, $n);
 
return 0;
?>


Javascript




<script>
// Javascript program to count minimum operations
// required to remove an array
     
    let MAX = 100005;
     
    // Return the cost to convert two
    // numbers into consecutive prime number.
    function cost(a,b,prev,nxt)
    {
        let sub = a + b;
         
        if (a <= b && prev[b - 1] >= a)
        {
            return nxt[b] + prev[b - 1] - a - b;
        }
         
        a = Math.max(a, b);
        a = nxt[a];
        b = nxt[a + 1];
         
        return a + b - sub;
    }
     
    // Sieve to store next and previous
    // prime to a number.
    function sieve(prev,nxt)
    {
        let pr = new Array(MAX);
        for(let i=0;i<MAX;i++)
        {
            pr[i]=0;
        }
   
        pr[1] = 1;
        for (let i = 2; i < MAX; i++)
        {
            if (pr[i] == 1)
            {
                continue;
            }
       
            for (let j = i * 2; j < MAX; j += i)
            {
                pr[j] = 1;
            }
        }
       
        // Computing next prime each number.
        for (let i = MAX - 2; i > 0; i--)
        {
            if (pr[i] == 0)
            {
                nxt[i] = i;
            }
            else
            {
                nxt[i] = nxt[i + 1];
            }
        }
       
        // Computing previous prime each number.
        for (let i = 1; i < MAX; i++)
        {
            if (pr[i] == 0)
            {
                prev[i] = i;
            }
            else
            {
                prev[i] = prev[i - 1];
            }
        }
    }
     
    // Return the minimum number
    // of operation required.
    function minOperation(arr,nxt,prev,n)
    {
        let dp = new Array(n + 5);
        for(let i=0;i<n+5;i++)
        {
            dp[i]=new Array(n+5);
            for(let j=0;j<n+5;j++)
            {
                dp[i][j]=0;
            }
             
        }
   
        // For each index.
        for (let r = 0; r < n; r++)
        {
            // Each subarray.
            for (let l = r - 1; l >= 0; l -= 2)
            {
                dp[l][r] = Number.MAX_VALUE;
       
                for (let ad = l; ad < r; ad += 2)
                {
                    dp[l][r] = Math.min(dp[l][r], dp[l][ad] +
                                        dp[ad + 1][r - 1] +
                                        cost(arr[ad], arr[r],
                                                prev, nxt));
                }
            }
        }
       
        return dp[0][n - 1] + n / 2;
    }
     
    // Driver Code
    let arr=[1, 2, 4, 3];
    let n = arr.length;
    let nxt=new Array(MAX);
    let prev=new Array(MAX);
    sieve(prev, nxt);
   
    document.write(minOperation(arr, nxt, prev, n));
     
    // This code is contributed by rag2127
     
</script>


Output

5

Time Complexity: O(N3).

Space Complexity: O(N)



Last Updated : 20 Feb, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads