Minimum removals from array to make max – min <= K
Last Updated :
11 Nov, 2022
Given N integers and K, find the minimum number of elements that should be removed, such that Amax-Amin<=K. After the removal of elements, Amax and Amin is considered among the remaining elements.
Examples:
Input : a[] = {1, 3, 4, 9, 10, 11, 12, 17, 20}, k = 4
Output : 5
Explanation: Remove 1, 3, 4 from beginning and 17, 20 from the end.
Input : a[] = {1, 5, 6, 2, 8} K=2
Output : 3
Explanation: There are multiple ways to remove elements in this case.
One among them is to remove 5, 6, 8.
The other is to remove 1, 2, 5
Approach: Sort the given elements. Using the greedy approach, the best way is to remove the minimum element or the maximum element and then check if Amax-Amin <= K. There are various combinations of removals that have to be considered. We write a recurrence relation to try every possible combination. There will be two possible ways of removal, either we remove the minimum or we remove the maximum.
Let(i…j) be the index of elements left after removal of elements. Initially, we start with i=0 and j=n-1 and the number of elements removed is 0 at the beginning. We only remove an element if a[j]-a[i]>k, the two possible ways of removal are (i+1…j) or (i…j-1). The minimum of the two is considered.
Let DPi, j be the number of elements that need to be removed so that after removal a[j]-a[i]<=k.
Recurrence relation for sorted array:
DPi, j = 1+ (min(countRemovals(i+1, j), countRemovals(i, j-1))
Below is the implementation of the above idea:
C++
#include <bits/stdc++.h>
using namespace std;
#define MAX 100
int dp[MAX][MAX];
int countRemovals( int a[], int i, int j, int k)
{
if (i >= j)
return 0;
else if ((a[j] - a[i]) <= k)
return 0;
else if (dp[i][j] != -1)
return dp[i][j];
else if ((a[j] - a[i]) > k) {
dp[i][j] = 1 + min(countRemovals(a, i + 1, j, k),
countRemovals(a, i, j - 1, k));
}
return dp[i][j];
}
int removals( int a[], int n, int k)
{
sort(a, a + n);
memset (dp, -1, sizeof (dp));
if (n == 1)
return 0;
else
return countRemovals(a, 0, n - 1, k);
}
int main()
{
int a[] = { 1, 3, 4, 9, 10, 11, 12, 17, 20 };
int n = sizeof (a) / sizeof (a[0]);
int k = 4;
cout << removals(a, n, k);
return 0;
}
|
Java
import java.util.Arrays;
class GFG
{
static int MAX= 100 ;
static int dp[][]= new int [MAX][MAX];
static int countRemovals( int a[], int i, int j, int k)
{
if (i >= j)
return 0 ;
else if ((a[j] - a[i]) <= k)
return 0 ;
else if (dp[i][j] != - 1 )
return dp[i][j];
else if ((a[j] - a[i]) > k) {
dp[i][j] = 1 + Math.min(countRemovals(a, i + 1 , j, k),
countRemovals(a, i, j - 1 , k));
}
return dp[i][j];
}
static int removals( int a[], int n, int k)
{
Arrays.sort(a);
for ( int [] rows:dp)
Arrays.fill(rows,- 1 );
if (n == 1 )
return 0 ;
else
return countRemovals(a, 0 , n - 1 , k);
}
public static void main (String[] args)
{
int a[] = { 1 , 3 , 4 , 9 , 10 , 11 , 12 , 17 , 20 };
int n = a.length;
int k = 4 ;
System.out.print(removals(a, n, k));
}
}
|
Python3
MAX = 100
dp = [[ 0 for i in range ( MAX )]
for i in range ( MAX )]
for i in range ( 0 , MAX ) :
for j in range ( 0 , MAX ) :
dp[i][j] = - 1
def countRemovals(a, i, j, k) :
global dp
if (i > = j) :
return 0
elif ((a[j] - a[i]) < = k) :
return 0
elif (dp[i][j] ! = - 1 ) :
return dp[i][j]
elif ((a[j] - a[i]) > k) :
dp[i][j] = 1 + min (countRemovals(a, i + 1 ,
j, k),
countRemovals(a, i,
j - 1 , k))
return dp[i][j]
def removals(a, n, k) :
a.sort()
if (n = = 1 ) :
return 0
else :
return countRemovals(a, 0 ,
n - 1 , k)
a = [ 1 , 3 , 4 , 9 , 10 ,
11 , 12 , 17 , 20 ]
n = len (a)
k = 4
print (removals(a, n, k))
|
C#
using System;
class GFG
{
static int MAX = 100;
static int [,]dp = new int [MAX, MAX];
static int countRemovals( int []a, int i,
int j, int k)
{
if (i >= j)
return 0;
else if ((a[j] - a[i]) <= k)
return 0;
else if (dp[i, j] != -1)
return dp[i, j];
else if ((a[j] - a[i]) > k)
{
dp[i, j] = 1 + Math.Min(countRemovals(a, i + 1,
j, k),
countRemovals(a, i,
j - 1, k));
}
return dp[i, j];
}
static int removals( int []a,
int n, int k)
{
Array.Sort(a);
for ( int i = 0; i < MAX; i++)
{
for ( int j = 0; j < MAX; j++)
dp[i, j] = -1;
}
if (n == 1)
return 0;
else
return countRemovals(a, 0,
n - 1, k);
}
static void Main()
{
int []a = new int []{ 1, 3, 4, 9, 10,
11, 12, 17, 20 };
int n = a.Length;
int k = 4;
Console.Write(removals(a, n, k));
}
}
|
PHP
<?php
$MAX = 100;
$dp = array ( array ());
for ( $i = 0; $i < $MAX ; $i ++)
{
for ( $j = 0; $j < $MAX ; $j ++)
$dp [ $i ][ $j ] = -1;
}
function countRemovals( $a , $i ,
$j , $k )
{
global $dp ;
if ( $i >= $j )
return 0;
else if (( $a [ $j ] - $a [ $i ]) <= $k )
return 0;
else if ( $dp [ $i ][ $j ] != -1)
return $dp [ $i ][ $j ];
else if (( $a [ $j ] - $a [ $i ]) > $k )
{
$dp [ $i ][ $j ] = 1 + min(countRemovals( $a , $i + 1,
$j , $k ),
countRemovals( $a , $i ,
$j - 1, $k ));
}
return $dp [ $i ][ $j ];
}
function removals( $a , $n , $k )
{
sort( $a );
if ( $n == 1)
return 0;
else
return countRemovals( $a , 0,
$n - 1, $k );
}
$a = array (1, 3, 4, 9, 10,
11, 12, 17, 20);
$n = count ( $a );
$k = 4;
echo (removals( $a , $n , $k ));
?>
|
Javascript
<script>
let MAX = 100;
let dp = new Array(MAX);
for (let i = 0; i < MAX; i++)
{
dp[i] = new Array(MAX);
}
function countRemovals(a,i,j,k)
{
if (i >= j)
return 0;
else if ((a[j] - a[i]) <= k)
return 0;
else if (dp[i][j] != -1)
return dp[i][j];
else if ((a[j] - a[i]) > k) {
dp[i][j] = 1 + Math.min(countRemovals(a, i + 1, j, k),
countRemovals(a, i, j - 1, k));
}
return dp[i][j];
}
function removals(a,n,k)
{
a.sort( function (a, b){ return a - b});
for (let i = 0; i < MAX; i++)
{
for (let j = 0; j < MAX; j++)
{
dp[i][j] = -1;
}
}
if (n == 1)
return 0;
else
return countRemovals(a, 0, n - 1, k);
}
let a = [ 1, 3, 4, 9, 10, 11, 12, 17, 20 ];
let n = a.length;
let k = 4;
document.write(removals(a, n, k));
</script>
|
Time Complexity :O(n2)
Auxiliary Space: O(n2)
The solution could be further optimized. The idea is to sort the array in increasing order and traverse through all the elements (let’s say index i) and find the maximum element on its right (index j) such that arr[j] – arr[i] <= k. Thus, the number of elements to be removed becomes n-(j-i+1). The minimum number of elements can be found by taking the minimum of n-(j-i-1) overall i. The value of index j can be found through a binary search between start = i+1 and end = n-1;
C++
#include <bits/stdc++.h>
using namespace std;
int findInd( int key, int i,
int n, int k, int arr[])
{
int start, end, mid, ind = -1;
start = i + 1;
end = n - 1;
while (start < end)
{
mid = start + (end - start) / 2;
if (arr[mid] - key <= k)
{
ind = mid;
start = mid + 1;
}
else
{
end = mid;
}
}
return ind;
}
int removals( int arr[], int n, int k)
{
int i, j, ans = n - 1;
sort(arr, arr + n);
for (i = 0; i < n; i++)
{
j = findInd(arr[i], i, n, k, arr);
if (j != -1)
{
ans = min(ans, n - (j - i + 1));
}
}
return ans;
}
int main()
{
int a[] = {1, 3, 4, 9, 10,
11, 12, 17, 20};
int n = sizeof (a) / sizeof (a[0]);
int k = 4;
cout << removals(a, n, k);
return 0;
}
|
Java
import java.util.*;
class GFG{
static int findInd( int key, int i,
int n, int k, int arr[])
{
int start, end, mid, ind = - 1 ;
start = i + 1 ;
end = n - 1 ;
while (start < end)
{
mid = start + (end - start) / 2 ;
if (arr[mid] - key <= k)
{
ind = mid;
start = mid + 1 ;
}
else
{
end = mid;
}
}
return ind;
}
static int removals( int arr[], int n, int k)
{
int i, j, ans = n - 1 ;
Arrays.sort(arr);
for (i = 0 ; i < n; i++)
{
j = findInd(arr[i], i, n, k, arr);
if (j != - 1 )
{
ans = Math.min(ans,
n - (j - i + 1 ));
}
}
return ans;
}
public static void main(String args[])
{
int a[] = { 1 , 3 , 4 , 9 , 10 ,
11 , 12 , 17 , 20 };
int n = a.length;
int k = 4 ;
System.out.println(removals(a, n, k));
}
}
|
Python3
def findInd(key, i, n,
k, arr):
ind = - 1
start = i + 1
end = n - 1 ;
while (start < end):
mid = int (start +
(end - start) / 2 )
if (arr[mid] - key < = k):
ind = mid
start = mid + 1
else :
end = mid
return ind
def removals(arr, n, k):
ans = n - 1
arr.sort()
for i in range ( 0 , n):
j = findInd(arr[i], i,
n, k, arr)
if (j ! = - 1 ):
ans = min (ans, n -
(j - i + 1 ))
return ans
a = [ 1 , 3 , 4 , 9 ,
10 , 11 , 12 , 17 , 20 ]
n = len (a)
k = 4
print (removals(a, n, k))
|
C#
using System;
class GFG{
static int findInd( int key, int i,
int n, int k, int [] arr)
{
int start, end, mid, ind = -1;
start = i + 1;
end = n - 1;
while (start < end)
{
mid = start + (end - start) / 2;
if (arr[mid] - key <= k)
{
ind = mid;
start = mid + 1;
}
else
{
end = mid;
}
}
return ind;
}
static int removals( int [] arr, int n, int k)
{
int i, j, ans = n - 1;
Array.Sort(arr);
for (i = 0; i < n; i++)
{
j = findInd(arr[i], i, n, k, arr);
if (j != -1)
{
ans = Math.Min(ans,
n - (j - i + 1));
}
}
return ans;
}
static void Main()
{
int [] a = { 1, 3, 4, 9, 10,
11, 12, 17, 20 };
int n = a.Length;
int k = 4;
Console.Write(removals(a, n, k));
}
}
|
Javascript
<script>
function findInd(key , i , n , k , arr) {
var start, end, mid, ind = -1;
start = i + 1;
end = n - 1;
while (start < end) {
mid = start + (end - start) / 2;
if (arr[mid] - key <= k) {
ind = mid;
start = mid + 1;
}
else {
end = mid;
}
}
return ind;
}
function removals(arr , n , k) {
var i, j, ans = n - 1;
arr.sort((a,b)=>a-b);
for (i = 0; i < n; i++) {
j = findInd(arr[i], i, n, k, arr);
if (j != -1) {
ans = Math.min(ans, n - (j - i + 1));
}
}
return ans;
}
var a = [ 1, 3, 4, 9, 10, 11, 12, 17, 20 ];
var n = a.length;
var k = 4;
document.write(removals(a, n, k));
</script>
|
Time Complexity :O(nlogn)
Auxiliary Space: O(n)
Approach:
- The solution could be further optimized. The idea is to sort the array in increasing order and traverse through all the elements (let’s say index j) and find the minimum element on its left (index i) such that arr[j] – arr[i] <= k and store it in dp[j].
- Thus, the number of elements to be removed becomes n-(j-i+1). The minimum number of elements can be found by taking the minimum of n-(j-i-1) overall j. The value of index i can be found through its previous dp array element value.
Below is the implementation of the approach:
C++
#include<bits/stdc++.h>
using namespace std;
int removals( int arr[], int n, int k)
{
sort(arr, arr + n);
int dp[n];
for ( int i = 0; i < n; i++)
dp[i] = -1;
int ans = n - 1;
dp[0] = 0;
for ( int i = 1; i < n; i++)
{
dp[i] = i;
int j = dp[i - 1];
while (j != i && arr[i] - arr[j] > k)
{
j++;
}
dp[i] = min(dp[i], j);
ans = min(ans, (n - (i - j + 1)));
}
return ans;
}
int main()
{
int a[] = { 1, 3, 4, 9, 10, 11, 12, 17, 20 };
int n = sizeof (a) / sizeof (a[0]);
int k = 4;
cout<<removals(a, n, k);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
static int removals( int arr[], int n, int k)
{
Arrays.sort(arr);
int dp[] = new int [n];
Arrays.fill(dp, - 1 );
int ans = n - 1 ;
dp[ 0 ] = 0 ;
for ( int i = 1 ; i < n; i++) {
dp[i] = i;
int j = dp[i - 1 ];
while (j != i && arr[i] - arr[j] > k) {
j++;
}
dp[i] = Integer.min(dp[i], j);
ans = Integer.min(ans, (n - (i - j + 1 )));
}
return ans;
}
public static void main(String[] args)
{
int a[] = { 1 , 3 , 4 , 9 , 10 , 11 , 12 , 17 , 20 };
int n = a.length;
int k = 4 ;
System.out.print(removals(a, n, k));
}
}
|
Python3
def removals(arr, n, k):
arr.sort()
dp = [ 0 for i in range (n)]
for i in range (n):
dp[i] = - 1
ans = n - 1
dp[ 0 ] = 0
for i in range ( 1 , n):
dp[i] = i
j = dp[i - 1 ]
while (j ! = i and arr[i] - arr[j] > k):
j + = 1
dp[i] = min (dp[i], j)
ans = min (ans, (n - (i - j + 1 )))
return ans
a = [ 1 , 3 , 4 , 9 , 10 , 11 , 12 , 17 , 20 ]
n = len (a)
k = 4
print (removals(a, n, k))
|
C#
using System;
class GFG{
static int removals( int [] arr, int n, int k)
{
Array.Sort(arr);
int [] dp = new int [n];
for ( int i = 0; i < n; i++)
dp[i] = -1;
int ans = n - 1;
dp[0] = 0;
for ( int i = 1; i < n; i++)
{
dp[i] = i;
int j = dp[i - 1];
while (j != i && arr[i] - arr[j] > k)
{
j++;
}
dp[i] = Math.Min(dp[i], j);
ans = Math.Min(ans, (n - (i - j + 1)));
}
return ans;
}
static public void Main()
{
int [] a = { 1, 3, 4, 9, 10, 11, 12, 17, 20 };
int n = a.Length;
int k = 4;
Console.Write(removals(a, n, k));
}
}
|
Javascript
<script>
function removals(arr, n, k)
{
arr.sort((a,b)=>a-b);
var dp = Array(n);
for ( var i = 0; i < n; i++)
dp[i] = -1;
var ans = n - 1;
dp[0] = 0;
for ( var i = 1; i < n; i++)
{
dp[i] = i;
var j = dp[i - 1];
while (j != i && arr[i] - arr[j] > k)
{
j++;
}
dp[i] = Math.min(dp[i], j);
ans = Math.min(ans, (n - (i - j + 1)));
}
return ans;
}
var a = [1, 3, 4, 9, 10, 11, 12, 17, 20];
var n = a.length;
var k = 4;
document.write( removals(a, n, k));
</script>
|
Time Complexity: O(nlog n). As outer loop is going to make n iterations. And the inner loop iterates at max n times for all outer iterations. Because we start value of j from dp[i-1] and loops it until it reaches i and then for the next element we again start from the previous dp[i] value. So the total time complexity is O(n) if we don’t consider the complexity of the sorting as it is not considered in the above solution as well.
Auxiliary Space: O(n)
Space Optimised Approach
The solution could be further optimized. It can be done in Auxiliary Space: O(1). The idea is to first sort the array in ascending order. The keep 2 pointers, say i and j, where j iterates from index 1 to index n-1 and keeps track of ending subarray with the difference in max and min less than k, and i keeps the track of starting index of the subarray. If we find that a[j] – a[i[ <=k (means the i to j subarray is valid) we update the length from i to j in a variable to track of max length so far. Else, we update the starting index i with i+1.
At first it seems that subarrays from i to j are ignored, but obviously their lengths are less than i to j subarray, so we don’t care about them.
C++
#include<bits/stdc++.h>
using namespace std;
int removal( int a[], int n, int k)
{
sort(a, a + n);
int maxLen = INT_MIN;
int i = 0;
for ( int j = 0; j < n && i < n; j++) {
if (a[j] - a[i] <= k) {
maxLen = max(maxLen, j - i + 1);
}
else {
i++;
}
}
int removed = n - maxLen;
return removed;
}
int main()
{
int a[] = { 1, 3, 4, 9, 10, 11, 12, 17, 20 };
int n = sizeof (a) / sizeof (a[0]);
int k = 4;
cout << removal(a, n, k);
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
public static int removal( int [] a, int n, int k){
Arrays.sort(a);
int max = Integer.MIN_VALUE;
int i= 0 ;
for ( int j= 0 ;j<n && i<n;j++){
if (a[j]-a[i] <= k){
max = Math.max(max, j-i+ 1 );
}
else {
i++;
}
}
int removed = n-max;
return removed;
}
public static void main (String[] args) {
int a[] = { 1 , 3 , 4 , 9 , 10 , 11 , 12 , 17 , 20 };
int n = a.length;
int k = 4 ;
System.out.print(removal(a, n, k));
}
}
|
Python
def removal(a, n, k):
a.sort()
maxLen = 0
i = 0
for j in range ( 0 , n):
if a[j] - a[i] < = k:
maxLen = max (maxLen, j - i + 1 )
else :
i = i + 1
if i > = n:
break
remove = n - maxLen
return remove
a = [ 1 , 3 , 4 , 9 , 10 , 11 , 12 , 17 , 20 ]
n = len (a)
k = 4
print (removal(a, n, k))
|
C#
using System;
class GFG {
static int removal( int [] a, int n, int k)
{
Array.Sort(a);
int max = Int32.MinValue;
int i = 0;
for ( int j = 0; j < n && i < n; j++)
{
if (a[j] - a[i] <= k) {
max = Math.Max(max, j - i + 1);
}
else {
i++;
}
}
int removed = n - max;
return removed;
}
public static void Main()
{
int [] a = { 1, 3, 4, 9, 10, 11, 12, 17, 20 };
int n = a.Length;
int k = 4;
Console.Write(removal(a, n, k));
}
}
|
Javascript
<script>
function removal(a, n, k)
{
a.sort((a,b)=>a-b)
let maxLen = 0;
let i = 0;
for (let j = 0; j < n; j++)
{
if (a[j]-a[i] <= k){
maxLen = Math.max(maxLen, j-i+1);
}
else i++;
if (i >= n) break ;
}
let remove = n-maxLen;
return remove;
}
let a = [1, 3, 4, 9, 10, 11, 12, 17, 20];
let n = a.length;
let k = 4;
document.write(removal(a, n, k), "</br>" )
</script>
|
Time Complexity: O(nlogn) For sorting the array, we require O(nlogn) time, and no extra space. And for calculating we only traverse the loop once, thus it has O(n) time complexity. So, overall time complexity is O(nlogn).
Auxiliary Space: O(1)
Approach:
Here we are applying sliding window, our will maintain a[max]-a[min]<=k. First, ascending order should be used to sort the array. The maintain two pointers, let’s call them I and j, j iterating from index 1 to index n-1 and keeping track of the ending subarray with the difference in max and min smaller than k, and I keeping track of the initial index of the subarray. We update the length from I to j in a variable to track the maximum length thus far if we discover that a[j] – a[i]=k (meaning the I to j subarray is legitimate). If not, we add i+1 to the beginning index i.
C++
#include <bits/stdc++.h>
using namespace std;
int removal( int a[], int n, int k)
{
sort(a, a + n);
int diff= 0;
int ans = 0;
for ( int i = 0, j = 0; i < n; i++) {
int diff = a[i] - a[j];
while (i >= j && diff > k) {
diff = a[i] - a[++j];
}
ans = max(ans, i - j + 1);
}
return n - ans;
}
int main()
{
int a[] = { 1, 3, 4, 9, 10, 11, 12, 17, 20 };
int n = sizeof (a) / sizeof (a[0]);
int k = 4;
cout << removal(a, n, k);
return 0;
}
|
Java
import java.util.*;
class GFG {
public static int removal( int [] a, int n, int k)
{
Arrays.sort(a);
int diff
= 0 ;
int ans = 0 ;
for ( int i = 0 , j = 0 ; i < n; i++)
{
diff = a[i] - a[j];
while (i >= j && diff > k) {
diff = a[i] - a[++j];
}
ans = Math.max(ans, i - j + 1 );
}
return n - ans;
}
public static void main(String[] args)
{
int a[]
= new int [] { 1 , 3 , 4 , 9 , 10 , 11 , 12 , 17 , 20 };
int n = a.length;
int k = 4 ;
System.out.print(removal(a, n, k));
}
}
|
Python3
def removal(a, n, k):
a.sort()
diff = 0
ans = 0
j = 0
for i in range (n):
diff = a[i] - a[j]
while (i > = j and diff > k):
j + = 1
diff = a[i] - a[j]
ans = max (ans, i - j + 1 )
return n - ans
a = [ 1 , 3 , 4 , 9 , 10 , 11 , 12 , 17 , 20 ]
n = len (a)
k = 4
print (removal(a, n, k))
|
C#
using System;
using System.Collections;
public class GFG {
static int removal( int [] a, int n, int k)
{
Array.Sort(a);
int diff
= 0;
int ans = 0;
for ( int i = 0, j = 0; i < n; i++) {
diff = a[i] - a[j];
while (i >= j && diff > k) {
diff = a[i] - a[++j];
}
ans = Math.Max(ans, i - j + 1);
}
return n - ans;
}
static public void Main()
{
int [] a
= new int [] { 1, 3, 4, 9, 10, 11, 12, 17, 20 };
int n = a.Length;
int k = 4;
Console.Write(removal(a, n, k));
}
}
|
Javascript
function removal(a, n, k)
{
a.sort();
let diff = 0;
let ans = 0;
for (let i = 0, j = 0; i < n; i++)
{
diff = a[i] - a[j];
while (i >= j && diff > k) {
diff = a[i] - a[++j];
}
ans = Math.max(ans, i - j);
}
return n - ans;
}
let a= [ 1, 3, 4, 9, 10, 11, 12, 17, 20 ];
let n = a.length;
let k = 4;
document.write(removal(a, n, k));
</script>
|
Time complexity: O(nlogn)
Auxiliary Space: O(1)
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...