# 0581. Shortest Unsorted Continuous Subarray ###### tags: `Leetcode` `Medium` `Stack` `Greedy` `Sorting` Link: https://leetcode.com/problems/shortest-unsorted-continuous-subarray/ ## 思路 ### 思路一 $O(N)$ $O(1)$ 非常直觉的解法 首先先找递减序列确定边界 [minIdx, maxIdx],因为递减序列无论如何都会要包含在要sort的subarray里面 然后找到这个subarray里面的最大和最小值 [minVal, maxVal] 再从[0, minIdx)里面找看有没有大于minVal的值,如果有左边界变成那个idx 再从(maxIdx, nums.length)里面倒序找看有没有小于maxVal的值,如果有有边界变成那个idx ### 思路二 $O(N)$ $O(1)$ 更简单的思路 速度也更快 简单来说 对于每一个元素都要看前面有没有元素比它大,后面有没有元素比它小 所以遍历两次 第一次正序 一直记录前面的最大值 如果最大值比现在元素大,就要记录位置 第二次倒序 一直记录前面的最小值 如果最小值比现在元素小,就要记录位置 ### 思路三 stack $O(N)$ $O(N)$ ## Code ### 思路一 ```java= class Solution { public int findUnsortedSubarray(int[] nums) { int minIdx = Integer.MAX_VALUE; int maxIdx = Integer.MIN_VALUE; for(int i = 0;i < nums.length-1;i++){ if(nums[i] > nums[i+1]){ minIdx = Math.min(minIdx, i); maxIdx = Math.max(maxIdx, i+1); } } if(minIdx == Integer.MAX_VALUE) return 0; int minVal = Integer.MAX_VALUE; int maxVal = Integer.MIN_VALUE; for(int i = minIdx;i <= maxIdx;i++){ minVal = Math.min(minVal, nums[i]); maxVal = Math.max(maxVal, nums[i]); } int l=minIdx, r=maxIdx; for(int i = 0;i < minIdx;i++){ if(nums[i] > minVal){ l = i; break; } } for(int i = nums.length-1;i > maxIdx;i--){ if(nums[i] < maxVal){ r = i; break; } } return r-l+1; } } ``` ### 思路二 ```java= class Solution { public int findUnsortedSubarray(int[] nums) { int n = nums.length; int right = 0, max = nums[0]; int left = n-1, min = nums[n-1]; for(int i=0; i<n; i++){ if(nums[i]<max) right = i; else max = nums[i]; } for(int i=n-1; i>=0; i--){ if(nums[i]>min) left = i; else min = nums[i]; } return right>left?right-left+1:0; } } ``` ### 思路三 ```java= class Solution { public int findUnsortedSubarray(int[] nums) { Stack<Integer> stack = new Stack<>(); int left = nums.length-1; for(int i = 0;i < nums.length;i++){ while(!stack.isEmpty() && nums[stack.peek()]>nums[i]){ left = Math.min(left, stack.pop()); } stack.push(i); } int right = 0; stack = new Stack<>(); for(int i = nums.length-1;i >= 0;i--){ while(!stack.isEmpty() && nums[stack.peek()]<nums[i]){ right = Math.max(right, stack.pop()); } stack.push(i); } if(left<right) return right-left+1; else return 0; } } ```