题目
给你一个整数数组 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
提示:
- 1 < = n u m s . l e n g t h < = 1 0 4 1 <= nums.length <= 10^4 1<=nums.length<=104
- − 1 0 5 < = n u m s [ i ] < = 1 0 5 -10^5 <= nums[i] <= 10^5 −105<=nums[i]<=105
进阶:你可以设计一个时间复杂度为 O(n) 的解决方案吗?
题解
方法一:排序
将原数组看作三段
n
u
m
s
A
,
n
u
m
s
B
,
n
u
m
s
C
nums_A, nums_B, nums_C
numsA,numsB,numsC,当我们对
n
u
m
s
B
nums_B
numsB排序后,整个数组即变得有序。根据题意要找到最短的
n
u
m
s
B
nums_B
numsB,那么即找到最长的
n
u
m
s
A
+
n
u
m
s
B
nums_A + nums_B
numsA+numsB。
因此我们将原数组
nums
\textit{nums}
nums排序与原数组进行比较,取最长的相同的前缀为
nums
A
\textit{nums}_A
numsA ,取最长的相同的后缀为
nums
C
\textit{nums}_C
numsC ,这样我们就可以取到最短的
nums
B
\textit{nums}_B
numsB。
特别地,当原数组有序时,
nums
B
\textit{nums}_B
numsB的长度为0,我们可以直接返回结果。
class Solution {
public int findUnsortedSubarray(int[] nums) {
if(isSort(nums)) return 0;
int len = nums.length;
if(len <= 1) return 0;
int[] sortNum = Arrays.copyOf(nums, len);
Arrays.sort(sortNum);
int left = 0, right = len - 1;
while(sortNum[left] == nums[left]) left++;
while(sortNum[right] == nums[right]) right--;
return right - left + 1;
}
public boolean isSort(int[] nums){
for(int i = 1; i < nums.length; i++){
if(nums[i] < nums[i - 1])
return false;
}
return true;
}
}
方法二:一次遍历(力扣)
class Solution {
public int findUnsortedSubarray(int[] nums) {
int n = nums.length;
int maxn = Integer.MIN_VALUE, right = -1;
int minn = Integer.MAX_VALUE, left = -1;
for (int i = 0; i < n; i++) {
if (maxn > nums[i]) {
right = i;
} else {
maxn = nums[i];
}
if (minn < nums[n - i - 1]) {
left = n - i - 1;
} else {
minn = nums[n - i - 1];
}
}
return right == -1 ? 0 : right - left + 1;
}
}