Last Updated: 6 Jan, 2021

Minimum Removals

Moderate
Asked in companies
AdobeRubrik, Inc.Microsoft

Problem statement

You have been given an array/list "ARR" consisting of 'N' integers. You have also given an integer 'K'.

Your task is to find the minimum number of elements that should be removed from "ARR" (possibly zero) such that the difference between the maximum element and the minimum element of the remaining "ARR" is less than or equal to 'K', i.e. ARRmax - ARRmin <= K.

Note :

1. "ARR" can contain duplicates.

For Example :

Input: 'N' = 4 , "ARR" =  [5, 10 , 2] and 'K' = 3.
Output: 1

Explanation : Currently, the difference between the maximum and minimum element in the array is 10 - 2 = 8, which is greater than K (3). 
So, we need to remove some elements. The optimal way to get our result is to remove 10. After removing 10, the difference between maximum and minimum is 5 - 2 = 3, which is less than or equal to K.
Input Format
The first line of input contains an integer 'T' which denotes the number of test cases or queries to be run. Then the test cases follow.

The first line of each test case contains two single-space separated integers ‘N’ and ‘K’, respectively.

The second line of each test case contains ‘N’ single space-separated integers, denoting the elements of the array/list.
Output Format :
Print the minimum number of elements that should be removed such that the difference between the maximum element and the minimum element of the remaining array is less than or equal to K.

Print the output of each test case in a separate line.

Note: You do not need to print anything; it has already been taken care of. Just implement the given function.
Constraints:
1 <= T <= 100
1 <= N <= 5000
0 <= K <= 10^5
-10^5 <= ARR[i] <=10^5

Where 'N' denotes the number of elements in the given array/list, 'K' is the given integer and ARR[i] denotes the i-th element of the given array/list.

Time Limit : 1 second

Approaches

01 Approach

The key observation here is that the best way to remove an element from the array is to remove the maximum or minimum element from the array. There are two possible ways of removal, either we remove the minimum element or the maximum element.

Now, the idea is to use recursion to reduce the big problem into several small subproblems. 

 

Here is the algorithm :

  1. We sort the array in ascending order.
  2. We will call a minRemovals function that returns us the minimum number of elements that should be removed such that the difference between the maximum element and minimum element of the remaining array is less than or equal to K. The minRemovals function will work as follows (here i and j denotes starting and ending index of ARR):
    1. If i >= j
      1. Return 0.
    2. If ARR[j] - ARR[i] <= K
      1. Return 0.
    3. Finally, we do a recursive call for (i + 1, j) and (i, j - 1) and 1 + minimum of them will be our answer.

02 Approach

If we draw the recursion tree for the recurrence relation of approach 1, we can observe that there are a lot of overlapping subproblems. There are only N^2 distinct recursive calls.

 

Lets understand this by an example, consider ARR = [1, 4, 8, 9]

The recursion tree for array will be :

 

As we can clearly see in the recursion tree that [4, 8] will be calculated twice.

Since the problem has overlapping subproblems, we can solve it more efficiently using memoization.

The algorithm is similar to the previous approach with some additions. 

 

We initialise a 2-D vector memo with -1. Now, memo[i][j] will store the minimum number of elements that should be removed such that the difference between the maximum element and minimum element of the array starting from index i and ending at j is less than or equal to K.

 

Before calling the function for any valid (i, j), we will check whether we already have a solution corresponding to the (i, j) present in memo

  1. If we already have a solution corresponding to (i, j), we return the solution.
  2. Else call the recursive function for (i+1, j) and (i, j-1) and store the minimum of them + 1 in memo[i][j] and return it..

03 Approach

Initially, we were breaking the large problem into small subproblems but now, let us look at it differently. The idea is to solve the small problem first and then reach the final answer. Thus we will be using a bottom-up approach now. 

 

Here is the algorithm:

  1. We will initialise a 2-D matrix dp filled with 0. dp[i][j] will store the minimum number of elements that should be removed such that the difference between the maximum element and minimum element of the array starting from index i and ending at j is less than or equal to K.
  2. Now we iterate over the matrix diagonally for i < j:
    1. If ARR[j] - ARR[i] <= K.
      1. dp[i][j] = 0. Since our condition is satisfied we don’t need to remove any element from the array.
    2. Else
      1. dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]) + 1.
  3. Finally, return dp[0][N - 1].

04 Approach

In this approach we will find the ending index(j) for each starting index(i) for which arr[j] - arr[i] <= K. The number of elements to be removed is N - (j - i + 1). We will maintain the minimum of it for each starting index from 0 to N - 1 and return it as the final result.

 

We will use binary search to find j (end index) for each i (starting index). It will reduce the time complexity to log(N) for each i.