题目描述
给你一个整数数组 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
提示:
进阶: 你可以设计一个时间复杂度为O(n)
的解决方案吗?
题目解析
初步思路--超时的解
- 首先题目仅要求输出最短子数组的长度
- 那么仅仅知道子数组左右边界的索引位置即可
- 利用一个辅助栈来维护递增的序列,栈顶元素最大
- 如果当前元素,小于栈顶元素那么需要进行交换,找到 当前元素应该处于数组对应的哪一个位置
- 然后这个时候可以记录更新一下
start、end
的位置
show code
class Solution {
public int findUnsortedSubarray(int[] nums) {
int n = nums.length;
if (n == 1) {
return 0;
}
// 用一个栈维护递增序列
Deque<Integer> stack = new LinkedList<>();
// 辅助栈,当 遇到元素小于 stack.peek() 的时候辅助交换元素
Deque<Integer> temporary = new LinkedList<>();
// start:记录 符合要求的子数组的开始位置
// end :记录符合要求的子数组的结束位置
int start = n, end = 0;
for (int num : nums) {
// 如果需要进行元素交换排序
while (!stack.isEmpty() && num < stack.peek()) {
temporary.push(stack.pop());
}
// 记录一次 start 的位置
if (!temporary.isEmpty()) {
start = Math.min(start, stack.size());
}
stack.push(num);
// 不断记录更新 end 的位置.
if (!temporary.isEmpty()) {
end = stack.size() + temporary.size() - 1;
}
while (!temporary.isEmpty()) {
stack.push(temporary.pop());
}
}
return start == n ? 0 : (end - start + 1);
}
}
- 但是超时了
- 因为两个栈来互相交换元素的过程太过耗时
优化解-O(n)时间复杂度
- 如果考虑只遍历常数次数组就能够得到最终结果呢?
- 首先我们仅仅需要得到左右边界
- 所以,最终应该要求得 “最短无序连续子数组” 中最大值和最小值对应的索引位置
- 那么这个 “最短无序连续子数组” 具有什么性质呢?
- 其位于原数组的中间
- 其最小值 大于 其左段的最大值
- 其最大值 小于 其右段的最小值
- 那么从左到右维护一个最大值
max
,那么在进入右段之前,所有的值都小于max
- 那么右边界
end
对应的就是最后一个小于max
的元素 - 同理,从右到左维护一个最小值
min
,在进入左段之前,所有的值都大于min
- 那么左边界
begin
就是最后一个大于min
元素的位置
show code
class Solution {
public int findUnsortedSubarray(int[] nums) {
int n = nums.length;
// 初始化一个最大值和一个最小值
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
// 初始化 begin end 对应 最短连续子数组 的左右边界
int begin = 0,end = -1;
// 开始遍历
for(int i = 0;i < n;i++) {
// 所有的 nums[i] 小于 max
// 找到最后一个小于 max 位置的索引
if(nums[i] < max) {
end = i;
} else {
max = nums[i];
}
// 所有的 nums[i] 大于min
// 寻找最后一个大于 min 位置的索引
if(nums[n - i - 1] > min) {
begin = n - i - 1;
} else {
min = nums[n - i - 1];
}
}
return end - begin + 1;
}
}
标签:leet,code,end,nums,int,581,min,数组,stack
From: https://blog.51cto.com/u_16079703/8944241