Find minimum possible size of array with given rules for removing elements
Last Updated :
11 Mar, 2024
Given an array of numbers and a constant k, minimize size of array with following rules for removing elements.
- Exactly three elements can be removed at one go.
- The removed three elements must be adjacent in array, i.e., arr[i], arr[i+1], arr[i+2]. And the second element must be k greater than first and third element must be k greater than second, i.e., arr[i+1] – arr[i] = k and arr[i+2]-arr[i+1] = k.
Example:
Input: arr[] = {2, 3, 4, 5, 6, 4}, k = 1
Output: 0
We can actually remove all elements.
First remove 4, 5, 6 => We get {2, 3, 4}
Now remove 2, 3, 4 => We get empty array {}
Input: arr[] = {2, 3, 4, 7, 6, 4}, k = 1
Output: 3
We can only remove 2 3 4
We strongly recommend you to minimize your browser and try this yourself first.
For every element arr[i] there are two possibilities.
1) Either the element is not removed.
2) OR element is removed (if it follows rules of removal). When an element is removed, there are again two possibilities.
…..a) It may be removed directly, i.e., initial arr[i+1] is arr[i]+k and arr[i+2] is arr[i] + 2*k.
…..b) There exist x and y such that arr[x] – arr[i] = k, arr[y] – arr[x] = k, and subarrays “arr[i+1…x-1]” & “arr[x+1…y-1]” can be completely removed.
Below is recursive algorithm based on above idea.
// Returns size of minimum possible size of arr[low..high]
// after removing elements according to given rules
findMinSize(arr[], low, high, k)
// If there are less than 3 elements in arr[low..high]
1) If high-low+1 < 3, return high-low+1
// Consider the case when 'arr[low]' is not considered as
// part of any triplet to be removed. Initialize result
// using this case
2) result = 1 + findMinSize(arr, low+1, high)
// Case when 'arr[low]' is part of some triplet and removed
// Try all possible triplets that have arr[low]
3) For all i from low+1 to high
For all j from i+1 to high
Update result if all of the following conditions are met
a) arr[i] - arr[low] = k
b) arr[j] - arr[i] = k
c) findMinSize(arr, low+1, i-1, k) returns 0
d) findMinSize(arr, i+1, j-1, k) also returns 0
e) Result calculated for this triplet (low, i, j)
is smaller than existing result.
4) Return result
The time complexity of above solution is exponential. If we draw the complete recursion tree, we can observer that many subproblems are solved again and again. Since same subproblems are called again, this problem has Overlapping Subproblems property. Like other typical Dynamic Programming(DP) problems, recomputations of same subproblems can be avoided by constructing a temporary array dp[][] to store results of the subproblems. Below is Dynamic Programming based solution
Below is the implementation of above idea. The implementation is memoization based, i.e., it is recursive and uses a lookup table dp[][] to check if a subproblem is already solved or not.
C++
#include <bits/stdc++.h>
using namespace std;
#define MAX 1000
int dp[MAX][MAX];
int minSizeRec( int arr[], int low, int high, int k)
{
if (dp[low][high] != -1)
return dp[low][high];
if ( (high-low + 1) < 3)
return high-low +1;
int res = 1 + minSizeRec(arr, low+1, high, k);
for ( int i = low+1; i<=high-1; i++)
{
for ( int j = i+1; j <= high; j++ )
{
if (arr[i] == (arr[low] + k) &&
arr[j] == (arr[low] + 2*k) &&
minSizeRec(arr, low+1, i-1, k) == 0 &&
minSizeRec(arr, i+1, j-1, k) == 0)
{
res = min(res, minSizeRec(arr, j+1, high, k));
}
}
}
return (dp[low][high] = res);
}
int minSize( int arr[], int n, int k)
{
memset (dp, -1, sizeof (dp));
return minSizeRec(arr, 0, n-1, k);
}
int main()
{
int arr[] = {2, 3, 4, 5, 6, 4};
int n = sizeof (arr)/ sizeof (arr[0]);
int k = 1;
cout << minSize(arr, n, k) << endl;
return 0;
}
|
Java
class GFG
{
static int MAX = 1000 ;
static int dp[][] = new int [MAX][MAX];
static int minSizeRec( int arr[], int low,
int high, int k)
{
if (dp[low][high] != - 1 )
{
return dp[low][high];
}
if ((high - low + 1 ) < 3 )
{
return high - low + 1 ;
}
int res = 1 + minSizeRec(arr,
low + 1 , high, k);
for ( int i = low + 1 ; i <= high - 1 ; i++)
{
for ( int j = i + 1 ; j <= high; j++)
{
if (arr[i] == (arr[low] + k) &&
arr[j] == (arr[low] + 2 * k) &&
minSizeRec(arr, low + 1 , i - 1 , k) == 0 &&
minSizeRec(arr, i + 1 , j - 1 , k) == 0 )
{
res = Math.min(res, minSizeRec(arr, j + 1 , high, k));
}
}
}
return (dp[low][high] = res);
}
static int minSize( int arr[], int n, int k)
{
for ( int i = 0 ; i < MAX; i++)
{
for ( int j = 0 ; j < MAX; j++)
{
dp[i][j] = - 1 ;
}
}
return minSizeRec(arr, 0 , n - 1 , k);
}
public static void main(String[] args)
{
int arr[] = { 2 , 3 , 4 , 5 , 6 , 4 };
int n = arr.length;
int k = 1 ;
System.out.println(minSize(arr, n, k));
}
}
|
Python3
MAX = 1000
dp = [[ - 1 for i in range ( MAX )] for i in range ( MAX )]
def minSizeRec(arr,low,high,k):
if dp[low][high] ! = - 1 :
return dp[low][high]
if (high - low + 1 ) < 3 :
return (high - low + 1 )
res = 1 + minSizeRec(arr, low + 1 , high, k)
for i in range (low + 1 ,high):
for j in range (i + 1 ,high + 1 ):
if (arr[i] = = (arr[low] + k) and arr[j] = = (arr[low] + 2 * k) and
minSizeRec(arr, low + 1 , i - 1 , k) = = 0 and
minSizeRec(arr, i + 1 , j - 1 , k) = = 0 ):
res = min (res,minSizeRec(arr,j + 1 ,high,k) )
dp[low][high] = res
return res
def minSize(arr,n,k):
dp = [[ - 1 for i in range ( MAX )] for i in range ( MAX )]
return minSizeRec(arr, 0 , n - 1 , k)
if __name__ = = '__main__' :
arr = [ 2 , 3 , 4 , 5 , 6 , 4 ]
n = len (arr)
k = 1
print (minSize(arr,n,k))
|
C#
using System;
class GFG
{
static int MAX = 1000;
static int [,]dp = new int [MAX, MAX];
static int minSizeRec( int []arr, int low,
int high, int k)
{
if (dp[low, high] != -1)
{
return dp[low, high];
}
if ((high - low + 1) < 3)
{
return high - low + 1;
}
int res = 1 + minSizeRec(arr,
low + 1, high, k);
for ( int i = low + 1; i <= high - 1; i++)
{
for ( int j = i + 1; j <= high; j++)
{
if (arr[i] == (arr[low] + k) &&
arr[j] == (arr[low] + 2 * k) &&
minSizeRec(arr, low + 1, i - 1, k) == 0 &&
minSizeRec(arr, i + 1, j - 1, k) == 0)
{
res = Math.Min(res, minSizeRec(arr, j + 1, high, k));
}
}
}
return (dp[low, high] = res);
}
static int minSize( int []arr, int n, int k)
{
for ( int i = 0; i < MAX; i++)
{
for ( int j = 0; j < MAX; j++)
{
dp[i, j] = -1;
}
}
return minSizeRec(arr, 0, n - 1, k);
}
public static void Main(String[] args)
{
int []arr = {2, 3, 4, 5, 6, 4};
int n = arr.Length;
int k = 1;
Console.WriteLine(minSize(arr, n, k));
}
}
|
Javascript
<script>
let MAX = 1000;
let dp = new Array(MAX);
for (let i = 0; i < MAX; i++)
{
dp[i] = new Array(MAX);
for (let j = 0; j < MAX; j++)
{
dp[i][j] = 0;
}
}
function minSizeRec(arr, low, high, k)
{
if (dp[low][high] != -1)
{
return dp[low][high];
}
if ((high - low + 1) < 3)
{
return high - low + 1;
}
let res = 1 + minSizeRec(arr, low + 1, high, k);
for (let i = low + 1; i <= high - 1; i++)
{
for (let j = i + 1; j <= high; j++)
{
if (arr[i] == (arr[low] + k) &&
arr[j] == (arr[low] + 2 * k) &&
minSizeRec(arr, low + 1, i - 1, k) == 0 &&
minSizeRec(arr, i + 1, j - 1, k) == 0)
{
res = Math.min(res, minSizeRec(arr, j + 1, high, k));
}
}
}
return (dp[low][high] = res);
}
function minSize(arr, n, k)
{
for (let i = 0; i < MAX; i++)
{
for (let j = 0; j < MAX; j++)
{
dp[i][j] = -1;
}
}
return minSizeRec(arr, 0, n - 1, k);
}
let arr = [2, 3, 4, 5, 6, 4];
let n = arr.length;
let k = 1;
document.write(minSize(arr, n, k));
</script>
|
Output:
0
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...