Removing Minimum and Maximum From Array
MedPrompt
You are given a 0-indexed array of distinct integers nums.
There is an element in nums that has the lowest value and an element that has the highest value. We call them the minimum and maximum respectively. Your goal is to remove both these elements from the array.
A deletion is defined as either removing an element from the front of the array or removing an element from the back of the array.
Return the minimum number of deletions it would take to remove both the minimum and maximum element from the array.
Example 1:
Input: nums = [2,10,7,5,4,1,8,6]
Output: 5
Explanation:
The minimum element in the array is nums[5], which is 1.
The maximum element in the array is nums[1], which is 10.
We can remove both the minimum and maximum by removing 2 elements from the front and 3 elements from the back.
This results in 2 + 3 = 5 deletions, which is the minimum number possible.Example 2:
Input: nums = [0,-4,19,1,8,-2,-3,5]
Output: 3
Explanation:
The minimum element in the array is nums[1], which is -4.
The maximum element in the array is nums[2], which is 19.
We can remove both the minimum and maximum by removing 3 elements from the front.
This results in only 3 deletions, which is the minimum number possible.Example 3:
Input: nums = [101]
Output: 1
Explanation:
There is only one element in the array, which makes it both the minimum and maximum element.
We can remove it with 1 deletion.
Constraints:
1 <= nums.length <= 105-105 <= nums[i] <= 105- The integers in
numsare distinct.
Approaches
2 approaches with complexity analysis and trade-offs.
This approach involves sorting the array to find the minimum and maximum elements. By sorting, the minimum element will be the first element and the maximum will be the last. However, we need their original indices. To preserve the original indices, we can create a helper data structure (like an array of pairs or objects) that stores both the value and its original index. After sorting this structure, we can easily retrieve the original indices of the minimum and maximum values and then calculate the minimum deletions required.
Algorithm
- Handle the edge case where the array has only one element. If
nums.length == 1, return 1. - Create a 2D array or an array of custom objects
indexedNumsof sizen x 2to store[value, original_index]. - Iterate through the input array
numsand populateindexedNums. For eachi, setindexedNums[i] = {nums[i], i}. - Sort
indexedNumsbased on the values (the first element of the pair). - The original index of the minimum element is
minIndex = indexedNums[0][1]. - The original index of the maximum element is
maxIndex = indexedNums[n-1][1]. - Define
left = min(minIndex, maxIndex)andright = max(minIndex, maxIndex). - Calculate the deletions for the three cases:
case1 = right + 1(deleting both from the front)case2 = n - left(deleting both from the back)case3 = (left + 1) + (n - right)(deleting one from each end)
- Return
min(case1, min(case2, case3)).
Walkthrough
The core idea is to find the indices of the minimum and maximum elements by sorting. Since sorting the original array would lose the index information, we first create an auxiliary array of pairs, where each pair contains an element from the input array and its original index.
We then sort this auxiliary array based on the element values. After sorting, the first element of the auxiliary array will correspond to the minimum value of the original array, and the last element will correspond to the maximum value.
From these two pairs, we extract their original indices. Let's call them minIndex and maxIndex.
With minIndex and maxIndex found, we can determine the minimum number of deletions. There are three possible scenarios to remove both elements:
- Remove from Front: Remove both elements by deleting from the front of the array. The number of deletions would be
max(minIndex, maxIndex) + 1. - Remove from Back: Remove both elements by deleting from the back of the array. The number of deletions would be
n - min(minIndex, maxIndex), wherenis the length of the array. - Remove from Both Ends: Remove one element from the front and the other from the back. The number of deletions would be
(min(minIndex, maxIndex) + 1) + (n - max(minIndex, maxIndex)).
The final answer is the minimum of the deletions calculated in these three scenarios.
import java.util.Arrays;import java.util.Comparator; class Solution { public int minimumDeletions(int[] nums) { int n = nums.length; if (n <= 1) { return n; } int[][] indexedNums = new int[n][2]; for (int i = 0; i < n; i++) { indexedNums[i][0] = nums[i]; indexedNums[i][1] = i; } Arrays.sort(indexedNums, Comparator.comparingInt(a -> a[0])); int minIndex = indexedNums[0][1]; int maxIndex = indexedNums[n - 1][1]; int left = Math.min(minIndex, maxIndex); int right = Math.max(minIndex, maxIndex); // Case 1: Remove both from the front int deletions1 = right + 1; // Case 2: Remove both from the back int deletions2 = n - left; // Case 3: Remove one from front, one from back int deletions3 = (left + 1) + (n - right); return Math.min(deletions1, Math.min(deletions2, deletions3)); }}Complexity
Time
O(N log N) due to the sorting step. Creating the indexed array takes `O(N)`, sorting takes `O(N log N)`, and the final calculations take `O(1)`. The dominant factor is sorting.
Space
O(N) to store the auxiliary `indexedNums` array.
Trade-offs
Pros
Conceptually straightforward if one is familiar with sorting.
Correctly solves the problem.
Cons
Not the most efficient solution in terms of time and space complexity.
Requires extra space, which can be significant for large arrays.
This is the most efficient approach. It involves iterating through the array just once to find the indices of the minimum and maximum elements. By maintaining variables to track the minimum value, maximum value, and their respective indices during a single pass, we can avoid the overhead of sorting. Once the indices are found, we use the same logic as the previous approach to calculate the minimum number of deletions based on the three possible removal strategies.
Algorithm
- Handle the edge case where the array has one or zero elements. If
nums.length <= 1, returnnums.length. - Initialize
minIndex = 0andmaxIndex = 0. - Iterate through the array
numsfromi = 0ton-1. - Inside the loop, if
nums[i] < nums[minIndex], updateminIndex = i. - If
nums[i] > nums[maxIndex], updatemaxIndex = i. - After the loop, define
left = min(minIndex, maxIndex)andright = max(minIndex, maxIndex). - Calculate the deletions for the three cases:
case1 = right + 1(deleting both from the front)case2 = n - left(deleting both from the back)case3 = (left + 1) + (n - right)(deleting one from each end)
- Return
min(case1, min(case2, case3)).
Walkthrough
The key to optimizing the problem is to find the indices of the minimum and maximum elements in linear time. This can be achieved with a single pass through the array.
We initialize variables to store the minimum and maximum element's indices, typically using the first element of the array.
We then iterate through the rest of the array. For each element, we compare it with the current minimum and maximum values. If the current element is smaller than the tracked minimum, we update the minimum's index. Similarly, if it's larger than the tracked maximum, we update the maximum's index.
After this single pass is complete, we will have the exact indices of the overall minimum and maximum elements in the array.
With these indices, minIndex and maxIndex, we analyze the three scenarios for removal:
- Remove from Front: Deleting from the front until the furthest of the two elements (
max(minIndex, maxIndex)) is removed. Cost:max(minIndex, maxIndex) + 1. - Remove from Back: Deleting from the back until the nearest of the two elements to the front (
min(minIndex, maxIndex)) is removed. Cost:n - min(minIndex, maxIndex). - Remove from Both Ends: Deleting from the front to remove the element with the smaller index, and from the back to remove the element with the larger index. Cost:
(min(minIndex, maxIndex) + 1) + (n - max(minIndex, maxIndex)).
The minimum of these three costs is the answer.
class Solution { public int minimumDeletions(int[] nums) { int n = nums.length; if (n <= 1) { return n; } int minIndex = 0; int maxIndex = 0; for (int i = 0; i < n; i++) { if (nums[i] < nums[minIndex]) { minIndex = i; } if (nums[i] > nums[maxIndex]) { maxIndex = i; } } int left = Math.min(minIndex, maxIndex); int right = Math.max(minIndex, maxIndex); // Case 1: Remove both from the front int deletions1 = right + 1; // Case 2: Remove both from the back int deletions2 = n - left; // Case 3: Remove one from front, one from back int deletions3 = (left + 1) + (n - right); return Math.min(deletions1, Math.min(deletions2, deletions3)); }}Complexity
Time
O(N) because we iterate through the array once to find the indices of the minimum and maximum elements. The subsequent calculations are O(1).
Space
O(1) as we only use a few variables to store indices, regardless of the input array size.
Trade-offs
Pros
Optimal time complexity.
Optimal space complexity.
Simple and efficient implementation.
Cons
None, this is the best possible solution.
Solutions
Solution
class Solution {public int minimumDeletions(int[] nums) { int mi = 0, mx = 0, n = nums.length; for (int i = 0; i < n; ++i) { if (nums[i] < nums[mi]) { mi = i; } if (nums[i] > nums[mx]) { mx = i; } } if (mi > mx) { int t = mx; mx = mi; mi = t; } return Math.min(Math.min(mx + 1, n - mi), mi + 1 + n - mx); }}class Solution {public: int minimumDeletions(vector<int> &nums) { int mi = 0, mx = 0, n = nums.size(); for (int i = 0; i < n; ++i) { if (nums[i] < nums[mi]) mi = i; if (nums[i] > nums[mx]) mx = i; } if (mi > mx) { int t = mi; mi = mx; mx = t; } return min(min(mx + 1, n - mi), mi + 1 + n - mx); }};class Solution: def minimumDeletions(self, nums: List[int]) -> int: mi = mx = 0 for i, num in enumerate(nums): if num < nums[mi]: mi = i if num > nums[mx]: mx = i if mi > mx: mi, mx = mx, mi return min(mx + 1, len(nums) - mi, mi + 1 + len(nums) - mx)Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.