Minimum deletions in Array to make difference of adjacent elements non-decreasing
Given an array A of N non-negative integers, the task is to compute the minimum number of elements to be deleted so, that the following conditions hold:
- The elements are in non-decreasing order. (Formally, for each i (1 ≤ i ≤ N-1), the condition Ai+1 >= Ai should hold.)
- The difference between adjacent elements should be in non-decreasing order. (Formally, for each i (2 ≤ i ≤ N-1), the condition Ai-Ai-1 ≤ Ai+1-Ai should hold.)
Examples:
Input: A = {1, 4, 5, 7, 20, 21}
Output:
2
Explanation: By deleting 5 and 21, the array {1, 4, 7, 20} is obtained. Here the elements are in non-decreasing order and the difference between adjacent elements are 3, 3, 13 which are in non-decreasing order.
Input: A = {3, 2}
Output:
1
Explanation: The original array doesn’t satisfy the first condition. Hence, either of the elements can be deleted to get an array with a single element.
Naive Approach: The naive approach is to generate all subsets of the given array and check whether any of the subsets satisfies the condition. If it does, check how many elements have been deleted to get that subset and, then, take the minimum.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int minimumDeletions( int A[], int N)
{
int ans = INT_MAX;
for ( int i = 1; i < (1 << N); i++) {
vector< int > temp;
for ( int j = 0; j < N; j++) {
if ((i & (1 << j)) != 0) {
temp.push_back(A[j]);
}
}
int flag = 0;
for ( int j = 1; j < temp.size(); j++)
if (temp[j] < temp[j - 1])
flag = 1;
for ( int j = 1; j < temp.size() - 1; j++)
if (temp[j] - temp[j - 1]
> temp[j + 1] - temp[j])
flag = 1;
if (flag == 0) {
ans = min(ans, N - ( int )temp.size());
}
}
return ans;
}
int main()
{
int A[] = { 1, 4, 5, 7, 20, 21 };
int N = sizeof (A) / sizeof (A[0]);
cout << minimumDeletions(A, N) << endl;
return 0;
}
|
Java
import java.util.ArrayList;
class GFG{
public static int minimumDeletions( int A[], int N)
{
int ans = Integer.MAX_VALUE;
for ( int i = 1 ; i < ( 1 << N); i++) {
ArrayList<Integer> temp = new ArrayList<Integer>();
for ( int j = 0 ; j < N; j++) {
if ((i & ( 1 << j)) != 0 ) {
temp.add(A[j]);
}
}
int flag = 0 ;
for ( int j = 1 ; j < temp.size(); j++)
if (temp.get(j) < temp.get(j - 1 ))
flag = 1 ;
for ( int j = 1 ; j < temp.size() - 1 ; j++)
if (temp.get(j) - temp.get(j - 1 )
> temp.get(j + 1 ) - temp.get(j))
flag = 1 ;
if (flag == 0 ) {
ans = Math.min(ans, N - ( int )temp.size());
}
}
return ans;
}
public static void main(String args[])
{
int A[] = { 1 , 4 , 5 , 7 , 20 , 21 };
int N = A.length;
System.out.println(minimumDeletions(A, N));
}
}
|
Python3
def minimumDeletions(A, N):
ans = 10 * * 8
for i in range ( 1 ,( 1 <<N)):
temp = []
for j in range (N):
if ((i & ( 1 << j)) ! = 0 ):
temp.append(A[j])
flag = 0
for j in range ( 1 , len (temp)):
if (temp[j] < temp[j - 1 ]):
flag = 1
for j in range ( 1 , len (temp) - 1 ):
if (temp[j] - temp[j - 1 ]> temp[j + 1 ] - temp[j]):
flag = 1
if (flag = = 0 ):
ans = min (ans, N - len (temp))
return ans
if __name__ = = '__main__' :
A = [ 1 , 4 , 5 , 7 , 20 , 21 ]
N = len (A)
print (minimumDeletions(A, N))
|
C#
using System;
using System.Collections.Generic;
class GFG{
static int minimumDeletions( int []A, int N)
{
int ans = Int32.MaxValue;
for ( int i = 1; i < (1 << N); i++) {
List< int > temp = new List< int >();
for ( int j = 0; j < N; j++) {
if ((i & (1 << j)) != 0) {
temp.Add(A[j]);
}
}
int flag = 0;
for ( int j = 1; j < temp.Count; j++)
if (temp[j] < temp[j - 1])
flag = 1;
for ( int j = 1; j < temp.Count - 1; j++)
if (temp[j] - temp[j - 1]
> temp[j + 1] - temp[j])
flag = 1;
if (flag == 0) {
ans = Math.Min(ans, N - temp.Count);
}
}
return ans;
}
public static void Main()
{
int []A = { 1, 4, 5, 7, 20, 21 };
int N = A.Length;
Console.Write(minimumDeletions(A, N));
}
}
|
Javascript
<script>
function minimumDeletions(A, N) {
let ans = Number.MAX_SAFE_INTEGER;
for (let i = 1; i < (1 << N); i++) {
let temp = [];
for (let j = 0; j < N; j++) {
if ((i & (1 << j)) != 0) {
temp.push(A[j]);
}
}
let flag = 0;
for (let j = 1; j < temp.length; j++)
if (temp[j] < temp[j - 1])
flag = 1;
for (let j = 1; j < temp.length - 1; j++)
if (temp[j] - temp[j - 1]
> temp[j + 1] - temp[j])
flag = 1;
if (flag == 0) {
ans = Math.min(ans, N - temp.length);
}
}
return ans;
}
let A = [1, 4, 5, 7, 20, 21];
let N = A.length;
document.write(minimumDeletions(A, N) + "<br>" );
</script>
|
Time Complexity: O(N*2N)
Auxiliary Space: O(N)
Efficient Approach using Dynamic programming: Instead of finding the minimum number of deletions, the problem can be solved by finding the maximum size of the subset, for which the conditions hold. Follow the steps below to solve the problem:
- Create a 2D array dp, where dp[i][j] stores the minimum number of elements to be deleted from index 1 to i, that satisfy the condition:
- A[i]-A[i-1]=A[j]
- Iterate from 0 to N-1 using i, and do the following:
- Store 1 in dp[i][0] as the size will be 1.
- Iterate from i-1 to 0 using j and do the following:
- Check if A[i] is greater than A[j]. If it is greater, do the following:
- Store A[i]-A[j] in a variable, say diff.
- Iterate from 0 to diff using k, and do the following:
- Store in dp[i] the maximum between dp[i] and dp[j][k]+1.
- Thus, the transition is:
- dp[i]=max(dp[i], dp[j][k]+1)
- Iterate from 0 to MAX using i, and store the maximum value of dp[N-1][i] in a variable, say maxSetSize.
- The answer would be N-maxSetSize.
Below is the code to implement the approach
C++
#include <bits/stdc++.h>
using namespace std;
#define MAX 100001
int minimumDeletions( int A[], int N)
{
int dp[N][MAX];
for ( int i = 0; i < N; i++)
for ( int j = 0; j < MAX; j++)
dp[i][j] = 0;
for ( int i = 0; i < N; i++) {
dp[i][0] = 1;
for ( int j = i - 1; j >= 0; j--) {
if (A[i] >= A[j]) {
int diff = A[i] - A[j];
for ( int k = 0; k <= diff; k++) {
dp[i]
= max(dp[i], dp[j][k] + 1);
}
}
}
}
int maxSetSize = -1;
for ( int i = 0; i < MAX; i++)
maxSetSize = max(maxSetSize, dp[N - 1][i]);
return N - maxSetSize;
}
int main()
{
int A[] = { 1, 4, 5, 7, 20, 21 };
int N = sizeof (A) / sizeof (A[0]);
cout << minimumDeletions(A, N) << endl;
return 0;
}
|
Java
import java.io.*;
class GFG {
static int MAX = 100001 ;
static int minimumDeletions( int A[], int N)
{
int [][] dp = new int [N][MAX];
for ( int i = 0 ; i < N; i++)
for ( int j = 0 ; j < MAX; j++)
dp[i][j] = 0 ;
for ( int i = 0 ; i < N; i++) {
dp[i][ 0 ] = 1 ;
for ( int j = i - 1 ; j >= 0 ; j--) {
if (A[i] >= A[j]) {
int diff = A[i] - A[j];
for ( int k = 0 ; k <= diff; k++) {
dp[i]
= Math.max(dp[i], dp[j][k] + 1 );
}
}
}
}
int maxSetSize = - 1 ;
for ( int i = 0 ; i < MAX; i++)
maxSetSize = Math.max(maxSetSize, dp[N - 1 ][i]);
return N - maxSetSize;
}
public static void main(String[] args)
{
int A[] = { 1 , 4 , 5 , 7 , 20 , 21 };
int N = A.length;
System.out.println(minimumDeletions(A, N));
}
}
|
Python3
MAX = 100001
def minimumDeletions(A, N):
global max
dp = [[ 0 for col in range ( MAX )] for row in range (N)]
for i in range (N):
for j in range ( MAX ):
dp[i][j] = 0
for i in range (N):
dp[i][ 0 ] = 1
for j in range (i - 1 , - 1 , - 1 ):
if (A[i] > = A[j]):
diff = A[i] - A[j]
for k in range (diff + 1 ):
dp[i] = max (dp[i],dp[j][k] + 1 )
maxSetSize = - 1
for i in range ( MAX ):
maxSetSize = max (maxSetSize, dp[N - 1 ][i])
return N - maxSetSize
A = [ 1 , 4 , 5 , 7 , 20 , 21 ]
N = len (A)
print (minimumDeletions(A, N))
|
C#
using System;
class GFG{
static int MAX = 100001;
static int minimumDeletions( int [] A, int N)
{
int [,] dp = new int [N, MAX];
for ( int i = 0; i < N; i++)
for ( int j = 0; j < MAX; j++)
dp[i, j] = 0;
for ( int i = 0; i < N; i++)
{
dp[i, 0] = 1;
for ( int j = i - 1; j >= 0; j--)
{
if (A[i] >= A[j])
{
int diff = A[i] - A[j];
for ( int k = 0; k <= diff; k++)
{
dp[i, diff] = Math.Max(dp[i, diff],
dp[j, k] + 1);
}
}
}
}
int maxSetSize = -1;
for ( int i = 0; i < MAX; i++)
maxSetSize = Math.Max(maxSetSize, dp[N - 1, i]);
return N - maxSetSize;
}
public static void Main()
{
int [] A = { 1, 4, 5, 7, 20, 21 };
int N = A.Length;
Console.Write(minimumDeletions(A, N));
}
}
|
Javascript
<script>
let MAX = 100001
function minimumDeletions(A, N)
{
let dp = new Array(N).fill(0).map(
() => new Array(MAX));
for (let i = 0; i < N; i++)
for (let j = 0; j < MAX; j++)
dp[i][j] = 0;
for (let i = 0; i < N; i++)
{
dp[i][0] = 1;
for (let j = i - 1; j >= 0; j--)
{
if (A[i] >= A[j])
{
let diff = A[i] - A[j];
for (let k = 0; k <= diff; k++)
{
dp[i] = Math.max(dp[i],
dp[j][k] + 1);
}
}
}
}
let maxSetSize = -1;
for (let i = 0; i < MAX; i++)
maxSetSize = Math.max(maxSetSize,
dp[N - 1][i]);
return N - maxSetSize;
}
let A = [ 1, 4, 5, 7, 20, 21 ];
let N = A.length;
document.write(minimumDeletions(A, N) + "<br>" );
</script>
|
Time complexity: O(N2*M), where M is the maximum element in A,
Auxiliary Space: O(N*M)
Efficient Approach using optimized Dynamic programming: In the above approach, the minimum from 0 to diff for each k is calculated repeatedly. To avoid this, a 2D prefix maximum array pref can be maintained where pref[i][j] stores the maximum of the size of subsets such that from 1 to i, the following condition holds:
- A[i]-A[i-1]=A[j]
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
#define MAX 100001
int minimumDeletions( int A[], int N)
{
int dp[N][MAX];
int pref[N][MAX];
for ( int i = 0; i < N; i++) {
for ( int j = 0; j < MAX; j++) {
dp[i][j] = 0;
pref[i][j] = 0;
}
}
for ( int i = 0; i < N; i++) {
dp[i][0] = 1;
for ( int j = i - 1; j >= 0; j--) {
if (A[i] >= A[j]) {
int diff = A[i] - A[j];
dp[i]
= max(dp[i], pref[j] + 1);
}
}
pref[i][0] = dp[i][0];
for ( int j = 1; j < MAX; j++)
pref[i][j] = max(dp[i][j], pref[i][j - 1]);
}
int maxSetSize = -1;
for ( int i = 0; i < MAX; i++)
maxSetSize = max(maxSetSize, dp[N - 1][i]);
return N - maxSetSize;
}
int main()
{
int A[] = { 1, 4, 5, 7, 20, 21 };
int N = sizeof (A) / sizeof (A[0]);
cout << minimumDeletions(A, N) << endl;
return 0;
}
|
Java
import java.io.*;
class GFG {
static int MAX = 100001 ;
static int minimumDeletions( int A[], int N)
{
int [][] dp = new int [N][MAX];
int [][] pref = new int [N][MAX];
for ( int i = 0 ; i < N; i++) {
for ( int j = 0 ; j < MAX; j++) {
dp[i][j] = 0 ;
pref[i][j] = 0 ;
}
}
for ( int i = 0 ; i < N; i++) {
dp[i][ 0 ] = 1 ;
for ( int j = i - 1 ; j >= 0 ; j--)
{
if (A[i] >= A[j])
{
int diff = A[i] - A[j];
dp[i]
= Math.max(dp[i], pref[j] + 1 );
}
}
pref[i][ 0 ] = dp[i][ 0 ];
for ( int j = 1 ; j < MAX; j++)
pref[i][j] = Math.max(dp[i][j], pref[i][j - 1 ]);
}
int maxSetSize = - 1 ;
for ( int i = 0 ; i < MAX; i++)
maxSetSize = Math.max(maxSetSize, dp[N - 1 ][i]);
return N - maxSetSize;
}
public static void main(String[] args)
{
int A[] = { 1 , 4 , 5 , 7 , 20 , 21 };
int N = A.length;
System.out.println(minimumDeletions(A, N));
}
}
|
Python3
MAX = 100001
def minimumDeletions(A, N):
dp = [[ 0 for i in range ( MAX )] for j in range (N)]
pref = [[ 0 for i in range ( MAX )] for j in range (N)]
for i in range (N):
dp[i][ 0 ] = 1
for j in range (i - 1 , - 1 , - 1 ):
if (A[i] > = A[j]):
diff = A[i] - A[j]
dp[i] = max (dp[i], pref[j] + 1 )
pref[i][ 0 ] = dp[i][ 0 ]
for j in range ( 1 , MAX ):
pref[i][j] = max (dp[i][j], pref[i][j - 1 ])
maxSetSize = - 1
for i in range ( MAX ):
maxSetSize = max (maxSetSize, dp[N - 1 ][i])
return N - maxSetSize
A = [ 1 , 4 , 5 , 7 , 20 , 21 ]
N = len (A)
print (minimumDeletions(A, N))
|
C#
using System;
class GFG {
static int MAX = 100001;
static int minimumDeletions( int []A, int N)
{
int [,] dp = new int [N,MAX];
int [,] pref = new int [N,MAX];
for ( int i = 0; i < N; i++) {
for ( int j = 0; j < MAX; j++) {
dp[i,j] = 0;
pref[i,j] = 0;
}
}
for ( int i = 0; i < N; i++) {
dp[i,0] = 1;
for ( int j = i - 1; j >= 0; j--)
{
if (A[i] >= A[j])
{
int diff = A[i] - A[j];
dp[i,diff]
= Math.Max(dp[i,diff], pref[j,diff] + 1);
}
}
pref[i,0] = dp[i,0];
for ( int j = 1; j < MAX; j++)
pref[i,j] = Math.Max(dp[i,j], pref[i,j - 1]);
}
int maxSetSize = -1;
for ( int i = 0; i < MAX; i++)
maxSetSize = Math.Max(maxSetSize, dp[N - 1,i]);
return N - maxSetSize;
}
public static void Main(String[] args)
{
int []A = { 1, 4, 5, 7, 20, 21 };
int N = A.Length;
Console.Write(minimumDeletions(A, N));
}
}
|
Javascript
<script>
var MAX = 100001;
function minimumDeletions(A, N)
{
var dp = new Array(N,MAX);
var pref = new Array(N,MAX);
for ( var i = 0; i < N; i++) {
for ( var j = 0; j < MAX; j++) {
dp[i,j] = 0;
pref[i,j] = 0;
}
}
for ( var i = 0; i < N; i++) {
dp[i,0] = 1;
for ( var j = i - 1; j >= 0; j--)
{
if (A[i] >= A[j])
{
var diff = A[i] - A[j];
dp[i]
= Math.max(dp[i,diff], pref[j,diff] + 1);
}
}
pref[i,0] = dp[i,0];
for ( var j = 1; j < MAX; j++)
pref[i,j] = Math.max(dp[i,j], pref[i,j - 1]);
}
var maxSetSize = -1;
for ( var i = 0; i < MAX; i++)
maxSetSize = Math.max(maxSetSize, dp[N - 1,i]);
return N - maxSetSize;
}
var A = [ 1, 4, 5, 7, 20, 21 ];
var N = A.length;
document.write(minimumDeletions(A, N));
</script>
|
Time complexity: O(N*M+N2), where M is the maximum element in A,
Auxiliary Space: O(N*M)
Last Updated :
06 May, 2022
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...