题目描述
给你一个整数数组 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 <= nums.length <= 104
-105 <= nums[i] <= 105
进阶:你可以设计一个时间复杂度为 O(n)
的解决方案吗?
解法
方法一:排序
我们可以先对数组进行排序,然后比较排序后的数组和原数组,找到最左边和最右边不相等的位置,它们之间的长度就是我们要找的最短无序连续子数组的长度。
时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 是数组的长度。
| class Solution:
def findUnsortedSubarray(self, nums: List[int]) -> int:
arr = sorted(nums)
l, r = 0, len(nums) - 1
while l <= r and nums[l] == arr[l]:
l += 1
while l <= r and nums[r] == arr[r]:
r -= 1
return r - l + 1
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14 | class Solution {
public int findUnsortedSubarray(int[] nums) {
int[] arr = nums.clone();
Arrays.sort(arr);
int l = 0, r = arr.length - 1;
while (l <= r && nums[l] == arr[l]) {
l++;
}
while (l <= r && nums[r] == arr[r]) {
r--;
}
return r - l + 1;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | class Solution {
public:
int findUnsortedSubarray(vector<int>& nums) {
vector<int> arr = nums;
sort(arr.begin(), arr.end());
int l = 0, r = arr.size() - 1;
while (l <= r && arr[l] == nums[l]) {
l++;
}
while (l <= r && arr[r] == nums[r]) {
r--;
}
return r - l + 1;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13 | func findUnsortedSubarray(nums []int) int {
arr := make([]int, len(nums))
copy(arr, nums)
sort.Ints(arr)
l, r := 0, len(arr)-1
for l <= r && nums[l] == arr[l] {
l++
}
for l <= r && nums[r] == arr[r] {
r--
}
return r - l + 1
}
|
1
2
3
4
5
6
7
8
9
10
11
12 | function findUnsortedSubarray(nums: number[]): number {
const arr = [...nums];
arr.sort((a, b) => a - b);
let [l, r] = [0, arr.length - 1];
while (l <= r && arr[l] === nums[l]) {
++l;
}
while (l <= r && arr[r] === nums[r]) {
--r;
}
return r - l + 1;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 | impl Solution {
pub fn find_unsorted_subarray(nums: Vec<i32>) -> i32 {
let inf = 1 << 30;
let n = nums.len();
let mut l = -1;
let mut r = -1;
let mut mi = inf;
let mut mx = -inf;
for i in 0..n {
if mx > nums[i] {
r = i as i32;
} else {
mx = nums[i];
}
if mi < nums[n - i - 1] {
l = (n - i - 1) as i32;
} else {
mi = nums[n - i - 1];
}
}
if r == -1 {
0
} else {
r - l + 1
}
}
}
|
方法二:维护左侧最大值和右侧最小值
我们可以从左到右遍历数组,维护一个最大值 $mx$,如果当前值小于 $mx$,说明当前值不在正确的位置上,我们更新右边界 $r$ 为当前位置。同理,我们可以从右到左遍历数组,维护一个最小值 $mi$,如果当前值大于 $mi$,说明当前值不在正确的位置上,我们更新左边界 $l$ 为当前位置。在初始化时,我们将 $l$ 和 $r$ 都初始化为 $-1$,如果 $l$ 和 $r$ 都没有被更新,说明数组已经有序,返回 $0$,否则返回 $r - l + 1$。
时间复杂度 $O(n)$,其中 $n$ 是数组的长度。空间复杂度 $O(1)$。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | class Solution:
def findUnsortedSubarray(self, nums: List[int]) -> int:
mi, mx = inf, -inf
l = r = -1
n = len(nums)
for i, x in enumerate(nums):
if mx > x:
r = i
else:
mx = x
if mi < nums[n - i - 1]:
l = n - i - 1
else:
mi = nums[n - i - 1]
return 0 if r == -1 else r - l + 1
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 | class Solution {
public int findUnsortedSubarray(int[] nums) {
final int inf = 1 << 30;
int n = nums.length;
int l = -1, r = -1;
int mi = inf, mx = -inf;
for (int i = 0; i < n; ++i) {
if (mx > nums[i]) {
r = i;
} else {
mx = nums[i];
}
if (mi < nums[n - i - 1]) {
l = n - i - 1;
} else {
mi = nums[n - i - 1];
}
}
return r == -1 ? 0 : r - l + 1;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | class Solution {
public:
int findUnsortedSubarray(vector<int>& nums) {
const int inf = 1e9;
int n = nums.size();
int l = -1, r = -1;
int mi = inf, mx = -inf;
for (int i = 0; i < n; ++i) {
if (mx > nums[i]) {
r = i;
} else {
mx = nums[i];
}
if (mi < nums[n - i - 1]) {
l = n - i - 1;
} else {
mi = nums[n - i - 1];
}
}
return r == -1 ? 0 : r - l + 1;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 | func findUnsortedSubarray(nums []int) int {
const inf = 1 << 30
n := len(nums)
l, r := -1, -1
mi, mx := inf, -inf
for i, x := range nums {
if mx > x {
r = i
} else {
mx = x
}
if mi < nums[n-i-1] {
l = n - i - 1
} else {
mi = nums[n-i-1]
}
}
if r == -1 {
return 0
}
return r - l + 1
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | function findUnsortedSubarray(nums: number[]): number {
let [l, r] = [-1, -1];
let [mi, mx] = [Infinity, -Infinity];
const n = nums.length;
for (let i = 0; i < n; ++i) {
if (mx > nums[i]) {
r = i;
} else {
mx = nums[i];
}
if (mi < nums[n - i - 1]) {
l = n - i - 1;
} else {
mi = nums[n - i - 1];
}
}
return r === -1 ? 0 : r - l + 1;
}
|