LeetCode 581 Shortest Unsorted Continuous Subarray 题解
题意
给定一个数组,找出一个最短的子序列使其满足,只将这个子序列重新排序即可使整个数组有序(升序)。输出这个最短子序列的长度。
思路
一 排序对比
比较容易想到的是将数组排序后与原数组对比。比如样例:
未排序 [2, 6, 4, 8, 10, 9, 15]
排序后 [2, 4, 6, 8, 9, 10, 15]
^ ^
很容就能得到结果。复杂度即为排序的复杂度O(logn)。
代码:
int findUnsortedSubarray(vector<int> &nums) {
vector<int> nums_cp(nums);
sort(nums.begin(), nums.end());
const int sz = nums.size();
int st = sz, ed = sz - 1;
for (int i = 0; i < sz; i++) {
if (nums[i] != nums_cp[i]) {
st = i;
break;
}
}
for (int i = sz - 1; i >= 0; i--) {
if (nums[i] != nums_cp[i]) {
ed = i;
break;
}
}
return ed - st + 1;
}
二 寻找不满足条件的数字
对于一个从小到大排列的数组(长度为n)来说,容易得到如下条件:第i
个数一定是0~i
中最大的数,是i~n
中最小的数。因此只需找到不满足上述条件的第一个和最后一个数即可:
-
从后往前寻找下标最小的不满足 第
i
个数是i~n
中最小的数 的元素; -
从前往后寻找下标最大的不满足 第
i
个数是0~i
中最大的数 的元素;
代码如下:
int findUnsortedSubarray(vector<int> &nums) {
const int sz = nums.size();
int st = 0, ed = -1;
int maxval = nums[0], minval = nums[sz - 1];
for (int i = 1; i < sz; i++) {
maxval = max(maxval, nums[i]);
minval = min(minval, nums[sz - i - 1]);
if (nums[i] < maxval)
ed = i;
if (nums[sz - i - 1] > minval)
st = sz - i - 1;
}
return ed - st + 1;
}
总结
第二种方法时间复杂度为O(n),空间复杂度为O(1),只需在遍历同时求最小值与最大值,不断更新开始位置和结束位置即可得到答案。