最短无序连续子数组
问题描述:
给你一个整数数组 nums ,你需要找出一个 连续子数组 ,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序。
请你找出符合题意的 最短 子数组,并输出它的长度。
示例1:
输入:nums = [2,6,4,8,10,9,15]
输出:5
解释:你只需要对 [6, 4, 8, 10, 9] 进行升序排序,那么整个表都会变为升序排序。
示例2:
输入:nums = [1,2,3,4]
输出:0
示例3:
输入:nums = [1]
输出:0
思路:
- 因为最后需要得到一个有序数组,需要子数组的左边界的值满足以下条件:
- 左边界的值大于左边界右边所有值中的最小值。
- 右边界的值小于右边界左边所有值中的最大值。
拿左边界来说,左边界右边的所有值中存在比左边界更小的值,那么这个更小的值就需要和左边界交换,右边界同理。
当然,这里并不是所有满足上面条件的都可以成为左边界,而是从左到右第一个满足这个条件的位置可以定义为左边界,同理,从右向左第一个满足右边界条件的位置定义为右边界。
- 定义两个数组,一个表示第 i 号元素前面元素的最大值,另一个表示第 i 号元素后面的最小值。
- 通过两个循环遍历求的整个数组
- 在从左向右遍历左边界,从右向左遍历右边界
java代码:
public int findUnsortedSubarray(int[] nums) {
int n = nums.length;
if(n==1){
return 0;
}
if(n==2){
return nums[0]<=nums[1]?0:2;
}
//pro[i]表示第i号元素前面最大的元素大小(包括i本身)
int[] pro = new int[n];
pro[0] = nums[0];
//end[i]表示第i号元素后面最小的元素的大小(包括i本身)
int[] end = new int[n];
end[n-1] = nums[n-1];
for (int i = 1; i < n; i++) {
pro[i] = Math.max(pro[i-1],nums[i]);
}
for (int i = n - 2; i >= 0; i--) {
end[i] = Math.min(end[i+1],nums[i]);
}
int pro_s = 0;
int end_s = 0;
for (int i = 0; i < n; i++) {
if(end[i]!=nums[i]){
pro_s = i;
break;
}
}
for (int i = n-1; i >=0 ; i--) {
if(pro[i]!=nums[i]){
end_s = i;
break;
}
}
return end_s==pro_s? 0:end_s-pro_s+1;
}