581. 最短无序连续子数组
思路:
这一题有点类似脑筋急转弯,我最开始的思路是先将原数组复制一遍排序,排序后从两边开始与原数组对比,找到两边不一样的数的索引,这段长度即为所求,但是这显然有点刻意,而且时间复杂度也不低。那么是否可以不排序直接找到两边的端点呢?
很简单,如果最右端的一部分已经排好序,这部分的每个数都比它左边的最大值要大,同理,如果最左端的一部分排好序,这每个数都比它右边的最小值小。所以我们从左往右遍历,如果i位置上的数比它左边部分最大值小,则这个数肯定要排序, 就这样找到右端不用排序的部分,同理找到左端不用排序的部分,它们之间就是需要排序的部分。
从左到右循环,记录最大值为 max,若 nums[i] < max, 则表明位置 i 需要调整, 直到遍历完所有数结束,记录需要调整的最大位置 i 为 high;。
同理,从右到左循环,记录最小值为 min, 若 nums[i] > min, 则表明位置 i 需要调整,直到遍历完所有数结束,记录需要调整的最小位置 i 为 low.
public int findUnsortedSubarray(int[] nums) {
if(nums.length <= 1) return 0;
int n = nums.length,r = 0,l = n-1,mx = nums[0],mn = nums[n-1];
for(int i=0;i<n;++i){
if(nums[i] < mx)
r = i;
else
mx =nums[i];
}
for(int i=n-1;i>=0;--i){
if(nums[i] > mn)
l = i;
else
mn = nums[i];
}
return r-l+1<=0? 0:r-l+1;
}