|
| 1 | +# Problem: Minimum Window Sort |
| 2 | + |
| 3 | +LeetCode problem: [581. Shortest Unsorted Continuous Subarray](https://leetcode.com/problems/shortest-unsorted-continuous-subarray/). |
| 4 | + |
| 5 | +Given an array, find the length of the smallest subarray in it which when sorted will sort the whole array. |
| 6 | + |
| 7 | +## Examples |
| 8 | + |
| 9 | +Example 1: |
| 10 | + |
| 11 | +```plaintext |
| 12 | +Input: [1, 2, 5, 3, 7, 10, 9, 12] |
| 13 | +Output: 5 |
| 14 | +Explanation: We need to sort only the subarray [5, 3, 7, 10, 9] to make the whole array sorted |
| 15 | +``` |
| 16 | + |
| 17 | +Example 2: |
| 18 | + |
| 19 | +```plaintext |
| 20 | +Input: [1, 3, 2, 0, -1, 7, 10] |
| 21 | +Output: 5 |
| 22 | +Explanation: We need to sort only the subarray [1, 3, 2, 0, -1] to make the whole array sorted |
| 23 | +``` |
| 24 | + |
| 25 | +Example 3: |
| 26 | + |
| 27 | +```plaintext |
| 28 | +Input: [1, 2, 3] |
| 29 | +Output: 0 |
| 30 | +Explanation: The array is already sorted |
| 31 | +``` |
| 32 | + |
| 33 | +Example 4: |
| 34 | + |
| 35 | +```plaintext |
| 36 | +Input: [3, 2, 1] |
| 37 | +Output: 3 |
| 38 | +Explanation: The whole array needs to be sorted. |
| 39 | +``` |
| 40 | + |
| 41 | +## Solution 1 |
| 42 | + |
| 43 | +The algorithm first creates a sorted copy of the input array. It then iterates through both the input and sorted arrays to identify the start and end indices of the unsorted subarray. |
| 44 | + |
| 45 | +By comparing corresponding elements in the input array and the sorted array, it finds the first and last positions where the elements differ. |
| 46 | + |
| 47 | +Complexity analysis: |
| 48 | + |
| 49 | +- Time complexity: O(N * LogN) |
| 50 | +- Space complexity: O(N) |
| 51 | + |
| 52 | +```python |
| 53 | +def findUnsortedSubarray(nums: List[int]) -> int: |
| 54 | + sorted_nums = list(sorted(nums)) |
| 55 | + |
| 56 | + start = None |
| 57 | + end = None |
| 58 | + for i in range(len(nums)): |
| 59 | + if nums[i] != sorted_nums[i]: |
| 60 | + if start is None: |
| 61 | + start = i |
| 62 | + end = i |
| 63 | + else: |
| 64 | + end = i |
| 65 | + |
| 66 | + return (end - start) + 1 if start is not None else 0 |
| 67 | +``` |
| 68 | + |
| 69 | +## Solution 2 |
| 70 | + |
| 71 | +The algorithm starts by identifying both the start and the end of the candidate unsorted subarray through the following steps: |
| 72 | + |
| 73 | +1. It begins from the start of the array to find the first element that is out of order (i.e., an element smaller than its previous element). |
| 74 | +2. Similarly, it starts from the end of the array to find the first element that is out of order (i.e., an element larger than its previous element). |
| 75 | + |
| 76 | +But sorting this subarray may not necessarily result in the entire array being sorted. Here is an example: |
| 77 | + |
| 78 | +```plaintext |
| 79 | +Input: [1, 3, 2, 0, -1, 7, 10] |
| 80 | +Sorting the numbers between '3' and '-1' will not sort the whole array: [1, -1, 0, 2, 3, 7, 10] |
| 81 | +``` |
| 82 | + |
| 83 | +This happens when any of the following two conditions is met: |
| 84 | + |
| 85 | +1. There is a number before the candidate unsorted subarray that is larger than any number in the unsorted subarray. |
| 86 | +2. There is a number after the candidate unsorted subarray that is smaller than any number in the unsorted subarray. |
| 87 | + |
| 88 | +To sort the entire array, it is necessary to include all such elements that are larger than the smallest element of the unsorted subarray and all elements that are smaller than the largest element of the unsorted subarray. |
| 89 | + |
| 90 | +Therefore, the final algorithm proceeds as follows: |
| 91 | + |
| 92 | +1. From the beginning of the array, find the first element that is out of order. This element marks the start of the candidate unsorted subarray. |
| 93 | +2. From the end of the array, find the first element that is out of order. This element marks the end of the candidate unsorted subarray. |
| 94 | +3. Find the minimum and maximum values within this unsorted subarray. |
| 95 | +4. Extend the subarray to the left to include any elements that are larger than the minimum value of the unsorted subarray. |
| 96 | +5. Similarly, extend the subarray to the right to include any elements that are smaller than the maximum value of the unsorted subarray. |
| 97 | + |
| 98 | +Complexity analysis: |
| 99 | + |
| 100 | +- Time complexity: O(N) |
| 101 | +- Space complexity: O(1) |
| 102 | + |
| 103 | +```python |
| 104 | +# O(N) time and O(1) space |
| 105 | +def findUnsortedSubarrayIndices(nums: List[int]) -> Tuple[Optional[int], Optional[int]]: |
| 106 | + left = 0 |
| 107 | + while left < len(nums) - 1 and nums[left] <= nums[left + 1]: |
| 108 | + left += 1 |
| 109 | + |
| 110 | + # if the array is sorted |
| 111 | + if left == len(nums) - 1: |
| 112 | + return None, None |
| 113 | + |
| 114 | + right = len(nums) - 1 |
| 115 | + while right > 0 and nums[right] >= nums[right - 1]: |
| 116 | + right -= 1 |
| 117 | + |
| 118 | + return left, right |
| 119 | + |
| 120 | +# O(N) time and O(1) space |
| 121 | +def findSubarrayMinimumAndMaximum(nums: List[int], start: int, end: int) -> Tuple[int, int]: |
| 122 | + minimum = float("inf") |
| 123 | + maximum = float("-inf") |
| 124 | + for i in range(start, end + 1): |
| 125 | + minimum = min(minimum, nums[i]) |
| 126 | + maximum = max(maximum, nums[i]) |
| 127 | + |
| 128 | + return minimum, maximum |
| 129 | + |
| 130 | +def findUnsortedSubarray(nums: List[int]) -> int: |
| 131 | + start, end = findUnsortedSubarrayIndices(nums) |
| 132 | + |
| 133 | + # if the array is sorted |
| 134 | + if start is None and end is None: |
| 135 | + return 0 |
| 136 | + |
| 137 | + # find minimum and maximum numbers in the unsorted subarray |
| 138 | + minimum, maximum = findSubarrayMinimumAndMaximum(nums, start, end) |
| 139 | + |
| 140 | + # expand the subarray to the left to include any element before the subarray |
| 141 | + # which is smaller than the minimum element of the unsorted subarray |
| 142 | + temp = start - 1 |
| 143 | + while temp >= 0: |
| 144 | + if nums[temp] > minimum: |
| 145 | + start = temp |
| 146 | + temp -= 1 |
| 147 | + |
| 148 | + # expand the subarray to the right to include any element after the subarray |
| 149 | + # which is larger than the maximum element of the unsorted subarray |
| 150 | + temp = end + 1 |
| 151 | + while temp <= len(nums) - 1: |
| 152 | + if nums[temp] < maximum: |
| 153 | + end = temp |
| 154 | + temp += 1 |
| 155 | + |
| 156 | + return (end - start) + 1 |
| 157 | +``` |
0 commit comments