Description
Given an integer array arr, remove a subarray (can be empty) from arr such that the remaining elements in arr are non-decreasing.
A subarray is a contiguous subsequence of the array.
Return the length of the shortest subarray to remove.
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.
Example 4:
Input: arr = [1]
Output: 0
Constraints:
- 1 <= arr.length <= 10^5
- 0 <= arr[i] <= 10^9
分析
题目的意思是:给你一个数组,要求移除一个子数组,然后剩下的数构成一个非递减数列,求移除的最小长度。这里可以把问题转换为保留数组的最大长度,找出最大长度就可以求出移除的最小长度了。
首先,移除的子数组必须是连续的,所以就只能移除中间的部分,有三种情况,包含开头,包含结尾,开头和结尾都包含。所以就分三种情况来写代码了,首先遍历求出开头最大长度非递减数列,然后求出尾部最大长度非递减数列,然后再遍历求中间的就行了。
代码
class Solution:
def findLengthOfShortestSubarray(self, arr: List[int]) -> int:
n=len(arr)
left_idx=0
right_idx=n-1
for i in range(n-1):
if(arr[i]<=arr[i+1]):
left_idx=i+1
else:
break
if(left_idx==n-1):
return 0
for i in range(n-1,left_idx,-1):
if(arr[i-1]<=arr[i]):
right_idx=i-1
else:
break
res=max(left_idx+1,n-right_idx)
i=0
j=right_idx
while(i<=left_idx and j<n):
if(arr[i]<=arr[j]):
res=max(res,i+1+n-j)
i+=1
else:
j+=1
return n-res