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
- 找以 arr[0]为开头的连续非递减数组的结尾 index, i
- 找以 arr[arr.len()-1]为结尾的连续非递减数组的开头 index, j
- 用 arr[…i]与 arr[j…]这两个数组来拼合出一个非递减数组
假设 dp[i][j]是用 arr[…i]与 arr[j…]删掉某些元素之后拼合成非递减数组所需要删除的最少元素数量, 那 dp[i][j] = min(dp[i-1][j], dp[i][j+1])。 注意考虑只用 arr[…i]或者只用 arr[j…]的情况, 因为这两个本身就是非递减的数组。
use std::collections::HashMap;
impl Solution {
fn dp(arr: &Vec<i32>, i: usize, j: usize, cache: &mut HashMap<(usize, usize), i32>) -> i32 {
if arr[i] <= arr[j] {
return (j - i - 1) as i32;
}
if i == 0 && j == arr.len() - 1 {
return arr.len() as i32 - 1;
}
if i == 0 {
let ans = if let Some(c) = cache.get(&(i, j + 1)) {
*c
} else {
Solution::dp(arr, i, j + 1, cache)
};
cache.insert((i, j), ans);
return ans;
}
if j == arr.len() - 1 {
let ans = if let Some(c) = cache.get(&(i - 1, j)) {
*c
} else {
Solution::dp(arr, i - 1, j, cache)
};
cache.insert((i, j), ans);
return ans;
}
let inc_j = if let Some(c) = cache.get(&(i, j + 1)) {
*c
} else {
Solution::dp(arr, i, j + 1, cache)
};
let dsc_i = if let Some(c) = cache.get(&(i - 1, j)) {
*c
} else {
Solution::dp(arr, i - 1, j, cache)
};
cache.insert((i, j), inc_j.min(dsc_i));
inc_j.min(dsc_i)
}
pub fn find_length_of_shortest_subarray(arr: Vec<i32>) -> i32 {
let left_endpoint = arr.windows(2).position(|l| l[0] > l[1]);
if left_endpoint.is_none() {
return 0;
}
let i = left_endpoint.unwrap();
let j = arr.len() - arr.windows(2).rev().position(|l| l[0] > l[1]).unwrap() - 1;
let only_left = arr.len() as i32 - (i as i32 + 1);
let only_right = arr.len() as i32 - (arr.len() as i32 - j as i32);
let mut ans = only_left.min(only_right);
ans = ans.min(Solution::dp(&arr, i, j, &mut HashMap::new()));
ans
}
}