Given an integer array arr, remove a subarray (can be empty) from arr such that the remaining elements in arr are non-decreasing.
Return the length of the shortest subarray to remove.
A subarray is a contiguous subsequence of the array.
Example 1:
Input: arr = [1,2,3,10,4,2,3,5]
Output: 3
Explanation: The shortest subarray we can remove is [10,4,2] of length 3. The remaining elements after that will be [1,2,3,3,5] which are sorted.
Another correct solution is to remove the subarray [3,10,4].
Example 2:
Input: arr = [5,4,3,2,1]
Output: 4
Explanation: Since the array is strictly decreasing, we can only keep a single element. Therefore we need to remove a subarray of length 4, either [5,4,3,2] or [4,3,2,1].
Example 3:
Input: arr = [1,2,3]
Output: 0
Explanation: The array is already non-decreasing. We do not need to remove any elements.
Constraints:
1 <= arr.length <= 105
0 <= arr[i] <= 109
Solutions
Solution 1: Two Pointers + Binary Search
First, we find the longest non-decreasing prefix and the longest non-decreasing suffix of the array, denoted as \(\textit{nums}[0..i]\) and \(\textit{nums}[j..n-1]\), respectively.
If \(i \geq j\), it means the array is already non-decreasing, so we return \(0\).
Otherwise, we can choose to delete the right suffix or the left prefix. Therefore, initially, the answer is \(\min(n - i - 1, j)\).
Next, we enumerate the right endpoint \(l\) of the left prefix. For each \(l\), we can use binary search to find the first position greater than or equal to \(\textit{nums}[l]\) in \(\textit{nums}[j..n-1]\), denoted as \(r\). At this point, we can delete \(\textit{nums}[l+1..r-1]\) and update the answer \(\textit{ans} = \min(\textit{ans}, r - l - 1)\). Continue enumerating \(l\) to get the final answer.
The time complexity is \(O(n \times \log n)\), where \(n\) is the length of the array. The space complexity is \(O(1)\).
Similar to Solution 1, we first find the longest non-decreasing prefix and the longest non-decreasing suffix of the array, denoted as \(\textit{nums}[0..i]\) and \(\textit{nums}[j..n-1]\), respectively.
If \(i \geq j\), it means the array is already non-decreasing, so we return \(0\).
Otherwise, we can choose to delete the right suffix or the left prefix. Therefore, initially, the answer is \(\min(n - i - 1, j)\).
Next, we enumerate the right endpoint \(l\) of the left prefix. For each \(l\), we directly use two pointers to find the first position greater than or equal to \(\textit{nums}[l]\) in \(\textit{nums}[j..n-1]\), denoted as \(r\). At this point, we can delete \(\textit{nums}[l+1..r-1]\) and update the answer \(\textit{ans} = \min(\textit{ans}, r - l - 1)\). Continue enumerating \(l\) to get the final answer.
The time complexity is \(O(n)\), where \(n\) is the length of the array. The space complexity is \(O(1)\).