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++
// CPP program to find minimum removals // to make max-min <= K #include <bits/stdc++.h> using namespace std; #define MAX 100 int dp[MAX][MAX]; // function to check all possible combinations // of removal and return the minimum one int countRemovals( int a[], int i, int j, int k) { // base case when all elements are removed if (i >= j) return 0; // if condition is satisfied, no more // removals are required else if ((a[j] - a[i]) <= k) return 0; // if the state has already been visited else if (dp[i][j] != -1) return dp[i][j]; // when Amax-Amin>d else if ((a[j] - a[i]) > k) { // minimum is taken of the removal // of minimum element or removal // of the maximum element dp[i][j] = 1 + min(countRemovals(a, i + 1, j, k), countRemovals(a, i, j - 1, k)); } return dp[i][j]; } // To sort the array and return the answer int removals( int a[], int n, int k) { // sort the array sort(a, a + n); // fill all stated with -1 // when only one element memset (dp, -1, sizeof (dp)); if (n == 1) return 0; else return countRemovals(a, 0, n - 1, k); } // Driver Code 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
// Java program to find minimum removals // to make max-min <= K import java.util.Arrays; class GFG { static int MAX= 100 ; static int dp[][]= new int [MAX][MAX]; // function to check all possible combinations // of removal and return the minimum one static int countRemovals( int a[], int i, int j, int k) { // base case when all elements are removed if (i >= j) return 0 ; // if condition is satisfied, no more // removals are required else if ((a[j] - a[i]) <= k) return 0 ; // if the state has already been visited else if (dp[i][j] != - 1 ) return dp[i][j]; // when Amax-Amin>d else if ((a[j] - a[i]) > k) { // minimum is taken of the removal // of minimum element or removal // of the maximum element dp[i][j] = 1 + Math.min(countRemovals(a, i + 1 , j, k), countRemovals(a, i, j - 1 , k)); } return dp[i][j]; } // To sort the array and return the answer static int removals( int a[], int n, int k) { // sort the array Arrays.sort(a); // fill all stated with -1 // when only one element for ( int [] rows:dp) Arrays.fill(rows,- 1 ); if (n == 1 ) return 0 ; else return countRemovals(a, 0 , n - 1 , k); } // Driver code 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)); } } // This code is contributed by Anant Agarwal. |
Python3
# Python program to find # minimum removals to # make max-min <= K 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 # function to check all # possible combinations # of removal and return # the minimum one def countRemovals(a, i, j, k) : global dp # base case when all # elements are removed if (i > = j) : return 0 # if condition is satisfied, # no more removals are required elif ((a[j] - a[i]) < = k) : return 0 # if the state has # already been visited elif (dp[i][j] ! = - 1 ) : return dp[i][j] # when Amax-Amin>d elif ((a[j] - a[i]) > k) : # minimum is taken of # the removal of minimum # element or removal of # the maximum element dp[i][j] = 1 + min (countRemovals(a, i + 1 , j, k), countRemovals(a, i, j - 1 , k)) return dp[i][j] # To sort the array # and return the answer def removals(a, n, k) : # sort the array a.sort() # fill all stated # with -1 when only # one element if (n = = 1 ) : return 0 else : return countRemovals(a, 0 , n - 1 , k) # Driver Code a = [ 1 , 3 , 4 , 9 , 10 , 11 , 12 , 17 , 20 ] n = len (a) k = 4 print (removals(a, n, k)) # This code is contributed by # Manish Shaw(manishshaw1) |
C#
// C# program to find minimum // removals to make max-min <= K using System; class GFG { static int MAX = 100; static int [,]dp = new int [MAX, MAX]; // function to check all // possible combinations // of removal and return // the minimum one static int countRemovals( int []a, int i, int j, int k) { // base case when all // elements are removed if (i >= j) return 0; // if condition is satisfied, // no more removals are required else if ((a[j] - a[i]) <= k) return 0; // if the state has // already been visited else if (dp[i, j] != -1) return dp[i, j]; // when Amax-Amin>d else if ((a[j] - a[i]) > k) { // minimum is taken of the // removal of minimum element // or removal of the maximum // element dp[i, j] = 1 + Math.Min(countRemovals(a, i + 1, j, k), countRemovals(a, i, j - 1, k)); } return dp[i, j]; } // To sort the array and // return the answer static int removals( int []a, int n, int k) { // sort the array Array.Sort(a); // fill all stated with -1 // when only one element 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); } // Driver code 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)); } } // This code is contributed by // ManishShaw(manishshaw1) |
PHP
<?php // PHP program to find // minimum removals to // make max-min <= K $MAX = 100; $dp = array ( array ()); for ( $i = 0; $i < $MAX ; $i ++) { for ( $j = 0; $j < $MAX ; $j ++) $dp [ $i ][ $j ] = -1; } // function to check all // possible combinations // of removal and return // the minimum one function countRemovals( $a , $i , $j , $k ) { global $dp ; // base case when all // elements are removed if ( $i >= $j ) return 0; // if condition is satisfied, // no more removals are required else if (( $a [ $j ] - $a [ $i ]) <= $k ) return 0; // if the state has // already been visited else if ( $dp [ $i ][ $j ] != -1) return $dp [ $i ][ $j ]; // when Amax-Amin>d else if (( $a [ $j ] - $a [ $i ]) > $k ) { // minimum is taken of // the removal of minimum // element or removal of // the maximum element $dp [ $i ][ $j ] = 1 + min(countRemovals( $a , $i + 1, $j , $k ), countRemovals( $a , $i , $j - 1, $k )); } return $dp [ $i ][ $j ]; } // To sort the array // and return the answer function removals( $a , $n , $k ) { // sort the array sort( $a ); // fill all stated with -1 // when only one element if ( $n == 1) return 0; else return countRemovals( $a , 0, $n - 1, $k ); } // Driver Code $a = array (1, 3, 4, 9, 10, 11, 12, 17, 20); $n = count ( $a ); $k = 4; echo (removals( $a , $n , $k )); // This code is contributed by // Manish Shaw(manishshaw1) ?> |
5
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 finding 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) over all i. The value of index j can be found through a binary search between start = i+1 and end = n-1;
C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; // Function to find // rightmost index // which satsfies the condition // arr[j] - arr[i] <= k int findInd( int key, int i, int n, int k, int arr[]) { int start, end, mid, ind = -1; // Initialising start to i + 1 start = i + 1; // Initialising end to n - 1 end = n - 1; // Binary search implementation // to find the rightmost element // that satisfy the condition while (start < end) { mid = start + (end - start) / 2; // Check if the condition satsfies if (arr[mid] - key <= k) { // Store the position ind = mid; // Make start = mid + 1 start = mid + 1; } else { // Make end = mid end = mid; } } // Return the rightmost position return ind; } // Function to calculate // minimum number of elements // to be removed int removals( int arr[], int n, int k) { int i, j, ans = n - 1; // Sort the given array sort(arr, arr + n); // Iterate from 0 to n-1 for (i = 0; i < n; i++) { // Find j such that // arr[j] - arr[i] <= k j = findInd(arr[i], i, n, k, arr); // If there exist such j // that satisfies the condition if (j != -1) { // Number of elements // to be removed for this // particular case is // (j - i + 1) ans = min(ans, n - (j - i + 1)); } } // Return answer return ans; } // Driver Code 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
// Java program for the above approach import java.util.*; class GFG{ // Function to find rightmost index // which satsfies the condition // arr[j] - arr[i] <= k static int findInd( int key, int i, int n, int k, int arr[]) { int start, end, mid, ind = - 1 ; // Initialising start to i + 1 start = i + 1 ; // Initialising end to n - 1 end = n - 1 ; // Binary search implementation // to find the rightmost element // that satisfy the condition while (start < end) { mid = start + (end - start) / 2 ; // Check if the condition satsfies if (arr[mid] - key <= k) { // Store the position ind = mid; // Make start = mid + 1 start = mid + 1 ; } else { // Make end = mid end = mid; } } // Return the rightmost position return ind; } // Function to calculate // minimum number of elements // to be removed static int removals( int arr[], int n, int k) { int i, j, ans = n - 1 ; // Sort the given array Arrays.sort(arr); // Iterate from 0 to n-1 for (i = 0 ; i < n; i++) { // Find j such that // arr[j] - arr[i] <= k j = findInd(arr[i], i, n, k, arr); // If there exist such j // that satisfies the condition if (j != - 1 ) { // Number of elements // to be removed for this // particular case is // (j - i + 1) ans = Math.min(ans, n - (j - i + 1 )); } } // Return answer return ans; } // Driver Code 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)); } } // This code is contributed by adityapande88 |
Python3
# Python program for the # above approach # Function to find # rightmost index # which satsfies the condition # arr[j] - arr[i] <= k def findInd(key, i, n, k, arr): ind = - 1 # Initialising start # to i + 1 start = i + 1 # Initialising end # to n - 1 end = n - 1 ; # Binary search implementation # to find the rightmost element # that satisfy the condition while (start < end): mid = int (start + (end - start) / 2 ) # Check if the condition # satsfies if (arr[mid] - key < = k): # Store the position ind = mid # Make start = mid + 1 start = mid + 1 else : # Make end = mid end = mid # Return the rightmost position return ind # Function to calculate # minimum number of elements # to be removed def removals(arr, n, k): ans = n - 1 # Sort the given array arr.sort() # Iterate from 0 to n-1 for i in range ( 0 , n): # Find j such that # arr[j] - arr[i] <= k j = findInd(arr[i], i, n, k, arr) # If there exist such j # that satisfies the condition if (j ! = - 1 ): # Number of elements # to be removed for this # particular case is # (j - i + 1) ans = min (ans, n - (j - i + 1 )) # Return answer return ans # Driver Code a = [ 1 , 3 , 4 , 9 , 10 , 11 , 12 , 17 , 20 ] n = len (a) k = 4 print (removals(a, n, k)) # This code is contributed by Stream_Cipher |
5
Time Complexity :O(nlogn)
Auxiliary Space: O(n)
Approach:
- The solution could be further optimised. The idea is to sort the array in increasing order and traverse through all the elements (let’s say index j) and finding 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) over all j. The value of index i can be found through its previous dp array element value.
Below is the implementation of the approach:
C++
// C++ program for the above approach #include<bits/stdc++.h> using namespace std; // To sort the array and return the answer int removals( int arr[], int n, int k) { // sort the array sort(arr, arr + n); int dp[n]; // fill all stated with -1 // when only one element for ( int i = 0; i < n; i++) dp[i] = -1; // as dp[0] = 0 (base case) so min // no of elements to be removed are // n-1 elements 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; } // Driver code 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; } // This code is contributed by Balu Nagar |
Java
// Java program for the above approach import java.io.*; import java.util.*; class GFG { // To sort the array and return the answer static int removals( int arr[], int n, int k) { // sort the array Arrays.sort(arr); // fill all stated with -1 // when only one element int dp[] = new int [n]; Arrays.fill(dp, - 1 ); // as dp[0] = 0 (base case) so min // no of elements to be removed are // n-1 elements int ans = n - 1 ; dp[ 0 ] = 0 ; // Iterate from 1 to n - 1 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; } // Driver code 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)); } } |
5
Time Complexity: O(n). As outer loop is going to make n interations. 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)
Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.