Minimum operations required to remove an array
Last Updated :
20 Feb, 2023
Given an array of N integers where N is even. There are two kinds of operations allowed on the array.
- Increase the value of any element A[i] by 1.
- 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++
#include<bits/stdc++.h>
#define MAX 100005
using namespace std;
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;
}
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;
}
for ( int i = MAX - 1; i; i--)
{
if (pr[i] == 0)
nxt[i] = i;
else
nxt[i] = nxt[i+1];
}
for ( int i = 1; i < MAX; i++)
{
if (pr[i] == 0)
prev[i] = i;
else
prev[i] = prev[i-1];
}
}
int minOperation( int arr[], int nxt[], int prev[], int n)
{
int dp[n + 5][n + 5] = { 0 };
for ( int r = 0; r < n; r++)
{
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;
}
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
class GFG
{
static final int MAX = 100005 ;
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;
}
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 ;
}
}
for ( int i = MAX - 2 ; i > 0 ; i--)
{
if (pr[i] == 0 )
{
nxt[i] = i;
}
else
{
nxt[i] = nxt[i + 1 ];
}
}
for ( int i = 1 ; i < MAX; i++)
{
if (pr[i] == 0 )
{
prev[i] = i;
}
else
{
prev[i] = prev[i - 1 ];
}
}
}
static int minOperation( int arr[], int nxt[],
int prev[], int n)
{
int dp[][] = new int [n + 5 ][n + 5 ];
for ( int r = 0 ; r < n; r++)
{
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 ;
}
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));
}
}
|
Python3
MAX = 100005
INT_MAX = 10000000
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
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
for i in range ( MAX - 2 , - 1 , - 1 ):
if (pr[i] = = 0 ):
nxt[i] = i
else :
nxt[i] = nxt[i + 1 ]
for i in range ( 1 , MAX ):
if (pr[i] = = 0 ):
prev[i] = i
else :
prev[i] = prev[i - 1 ]
def minOperation(arr, nxt, prev, n):
dp = [[ 0 for i in range (n + 5 )]
for i in range (n + 5 )]
for r in range (n):
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
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))
|
C#
using System;
class GFG
{
static int MAX = 100005;
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;
}
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;
}
}
for ( int i = MAX - 2; i > 0; i--)
{
if (pr[i] == 0)
{
nxt[i] = i;
}
else
{
nxt[i] = nxt[i + 1];
}
}
for ( int i = 1; i < MAX; i++)
{
if (pr[i] == 0)
{
prev[i] = i;
}
else
{
prev[i] = prev[i - 1];
}
}
}
static int minOperation( int [] arr, int [] nxt,
int [] prev, int n)
{
int [,] dp = new int [n + 5, n + 5];
for ( int r = 0; r < n; r++)
{
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;
}
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));
}
}
|
PHP
<?php
$MAX = 100005;
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 ;
}
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;
}
for ( $i = $MAX - 1; $i ; $i --)
{
if ( $pr [ $i ] == 0)
$nxt [ $i ] = $i ;
else
$nxt [ $i ] = $nxt [ $i +1];
}
for ( $i = 1; $i < $MAX ; $i ++)
{
if ( $pr [ $i ] == 0)
$prev [ $i ] = $i ;
else
$prev [ $i ] = $prev [ $i -1];
}
}
function minOperation(& $arr , & $nxt , & $prev , $n )
{
global $MAX ;
$dp = array_fill (0,( $n + 5), array_fill (0,( $n + 5),NULL));
for ( $r = 0; $r < $n ; $r ++)
{
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;
}
$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>
let MAX = 100005;
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;
}
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;
}
}
for (let i = MAX - 2; i > 0; i--)
{
if (pr[i] == 0)
{
nxt[i] = i;
}
else
{
nxt[i] = nxt[i + 1];
}
}
for (let i = 1; i < MAX; i++)
{
if (pr[i] == 0)
{
prev[i] = i;
}
else
{
prev[i] = prev[i - 1];
}
}
}
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 (let r = 0; r < n; r++)
{
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;
}
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));
</script>
|
Time Complexity: O(N3).
Space Complexity: O(N)
Share your thoughts in the comments
Please Login to comment...