# 581. Shortest Unsorted Continuous Subarray

**<font color=red>难度: Easy</font>**

## 刷题内容

> 原题连接

* https://leetcode.com/problems/shortest-unsorted-continuous-subarray/description/

> 内容描述

```
Given an integer array, you need to find one continuous subarray that if you only sort this subarray in ascending order, then the whole array will be sorted in ascending order, too.

You need to find the shortest such subarray and output its length.

Example 1:
Input: [2, 6, 4, 8, 10, 9, 15]
Output: 5
Explanation: You need to sort [6, 4, 8, 10, 9] in ascending order to make the whole array sorted in ascending order.
Note:
Then length of the input array is in range [1, 10,000].
The input array may contain duplicates, so ascending order here means <=.
```

## 解题方案

> 思路 1
 ******- 时间复杂度: O(NlgN)******- 空间复杂度: O(N)******

直接sort，然后找出sort前与sort后不同的数组长度


```python
class Solution(object):
    def findUnsortedSubarray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        start, end = 0, 0
        sorted_nums = sorted(nums)
        
        for i in range(len(nums)):
            if nums[i] != sorted_nums[i]:
                start = i
                break
        for i in range(len(nums)-1, -1, -1):
            if nums[i] != sorted_nums[i]:
                end = i
                break           
        
        return end - start + 1 if start != end else 0
```

> 思路 2
 ******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
 
这个方法我最推荐了

要满足三个性质：

1. nums[0, i - 1] and nums[j + 1, n - 1] are both sorted.
2. nums[i] != nums_sorted[i] and nums[j] != nums_sorted[j].
3. nums[i - 1] <= min and max <= nums[j + 1], where min and max are the minimum and maximum values of subarray nums[i, j].

所以我们需要做的就是 find the two longest sorted subarrays starting at index 0 and ending at index n - 1

- 从左到右找到第一个不满足nums[l] <= nums[l+1]的index l
- 然后从右到左找到第一个不满足nums[r] >= nums[r-1]的 index r
- 然后开始保证第三条性质，只要min(nums[l:r+1]) < nums[l]，l就自减1；只要max(nums[l:r+1]) > nums[r], r就自增1；
- 这两个index中间这一坨就是需要我们sort的最短subarray

参考[fun4LeetCode](https://leetcode.com/problems/shortest-unsorted-continuous-subarray/discuss/103066/Ideas-behind-the-O(n)-two-pass-and-one-pass-solutions)

two-pass，Finding the longest subarrays and the maximum and minimum values of the middle subarray takes one-pass. 
Ensuring the third property requires a second pass. 

```python
class Solution(object):
    def findUnsortedSubarray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        l, r = 0, len(nums) - 1
        while l < r and nums[l] <= nums[l+1]:
            l += 1
        if l >= r:
            return 0
        while r > 0 and nums[r] >= nums[r-1]:
            r -= 1
        max_num, min_num = -sys.maxsize, sys.maxsize
    
        for k in range(l, r+1):
            max_num = max(max_num, nums[k])
            min_num = min(min_num, nums[k])
        
        while l >= 0 and min_num < nums[l]:
            l -= 1
        while r < len(nums) and nums[r] < max_num:
            r += 1
        
        return r - l - 1
```

这里要注意第三条一定要满足


> 思路 3
 ******- 时间复杂度: O(N)******- 空间复杂度: O(1)******


1. 从左到右找到最后一个不符合递增规律的index end
2. 从右到左找到最后一个不符合递增规律的index start
3. 直接返回max(end-start+1, 0), 因为end可能比start小,比如对于输入[1,2,3,3,3]，end等于0，start等于4

```python
class Solution(object):
    def findUnsortedSubarray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        m = nums[0]
        end = 0
        for i in range(1, len(nums)):
            if nums[i] >= m:
                m = nums[i]
            else:
                end = i
                
        m = nums[-1]
        start = len(nums)-1
        for i in range(len(nums)-1, -1, -1):
            if nums[i] <= m:
                m = nums[i]
            else:
                start = i
        
        if start == end:
            return 0
                
        return max(end-start+1, 0)
```




> 思路 4
 ******- 时间复杂度: O(N)******- 空间复杂度: O(1)******
 
 one-pass
 
 这一次我们只需要找到
 
- i is the smallest index such that nums[i] != min[i:]
- j is the largest index such that nums[j] != max[:j+1]


```python
class Solution(object):
    def findUnsortedSubarray(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        i, j = 0, -1
        l, r = 0, len(nums) - 1
        max_num, min_num = -sys.maxsize, sys.maxsize
        while r >= 0:
            min_num = min(min_num, nums[r])
            # i is the smallest index such that nums[i] != min[i:]
            if nums[r] != min_num:
                i = r
            max_num = max(max_num, nums[l])
            # j is the largest index such that nums[j] != max[:j+1]
            if nums[l] != max_num:
                j = l
            l += 1
            r -= 1

        return j-i+1
```

