给你一个整数数组 nums
,你需要找出一个 连续子数组 ,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。请你找出符合题意的 最短 子数组,并输出它的长度。
示例 1:
输入:nums = [2,6,4,8,10,9,15]
输出:5
解释:你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。
今天刷的是这道题,一次遍历找出无序连续子数组的左右边界即可,简单说下思路,首先我们要搞清楚这个无序连续子数组的左右边界有什么特征,比如示例1中无序连续子数组是[6, 4, 8, 10, 9],仔细观察会发现6,4是降序,10,9也是降序,在一个升序数组中这都是异常的,由此可知这个无序连续子数组的左右边界肯定是降序的(对于一个升序数组来说),所以先从左往右遍历数组,然后维护一个max和end,max表示最大的数字,end表示出现降序的情况,即当nums[i - 1] > nums[i]时,更新 end = i,这样我们就可以找到无序连续子数组的右边界了,那么左边界如何寻找呢,我们可以从右往左遍历,这样就成了在一个降序数组中寻找无序连续子数组的右边界问题,同理维护一个min和begin,min表示最小的数字,begin表示出现升序的情况,即当nums[i] > nums[i + 1]时,更新begin = i,最后无序连续子数组的长度就是end - begin + 1。
文字有点多,主要是为了加深自己的印象,代码如下
class Solution {
public int findUnsortedSubarray(int[] nums) {
int length = nums.length;
if (length == 0 || length == 1)
return 0;
int min = nums[length - 1];
int max = nums[0];
int begin = 0, end = -1;
for (int i = 0; i < length; i++) {
// 从左往右遍历维护max,正常情况nums[length - 1]是最大的
if (nums[i] >= max) {
max = nums[i];
} else {
// 出现了降序,记录其下标
end = i;
}
// 从右往左遍历维护min,正常情况nums[0]是最小的
if (nums[length - 1 - i] <= min) {
min = nums[length - 1 - i];
} else {
// 出现了升序,记录其下标
begin = length - 1 - i;
}
}
return end - begin + 1;
}
}