Shortest Unsorted Continuous Subarray LT581

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:

  1. Then length of the input array is in range [1, 10,000].
  2. The input array may contain duplicates, so ascending order here means <=.

Idea 1. Similar to Max Chunks To Make Sorted II LT768, find the chunks and merge chunks by updating the end index, start index is the staring point of first chunk, the lengh = end index - start index.

The key point is: The array is considered sorted if the left elements are smaller or equal than the right elements, that is, the maximum of the left subarray is smaller or equal than the minimum of the right subarray.

The unsorted chunks can be found by:

a. store the minValue from right to left

b. stack in ascending order.

Time complexity: O(n)

Space complexity: O(n)

1.a

 1 class Solution {
 2     public int findUnsortedSubarray(int[] nums) {
 3         int sz = nums.length;
 4         int[] rightMin = new int[sz];
 5         rightMin[sz-1] = nums[sz-1];
 6
 7         for(int i = sz-2; i >= 0; --i) {
 8             rightMin[i] = Math.min(rightMin[i+1], nums[i]);
 9         }
10
11         int startIndex = -1;
12         int endIndex = -1;
13         int currMax = Integer.MIN_VALUE;
14         for(int i = 0; i + 1 < sz; ++i) {
15             currMax = Math.max(currMax, nums[i]);
16
17             if(currMax > rightMin[i+1]) {
18                 if(startIndex == -1) {
19                     startIndex = i;  // first unsorted chunk
20                 }
21                 else {
22                     endIndex = -1;  // new unsorted chunk, mark endIndex = -1 to merge
23                 }
24             }
25             else if(startIndex != -1 && endIndex == -1){
26                 endIndex = i;   // if curMax <= rightMin[i+1], means nums(i+1...end) is sorted
27             }
28         }
29
30         if(startIndex == -1) {
31             return 0;
32         }
33
34         if(endIndex == -1) {
35             endIndex = sz - 1;
36         }
37
38         return endIndex - startIndex + 1;
39     }
40 }

1.b stack

 1 class Solution {
 2     public int findUnsortedSubarray(int[] nums) {
 3        Deque<Integer> ascendingStack = new LinkedList<>();
 4
 5         int startIndex = nums.length;
 6         int endIndex = -1;
 7         int currMaxIndex = 0;
 8         for(int i = 0; i < nums.length; ++i) {
 9             if(currMaxIndex == nums.length || nums[currMaxIndex] < nums[i] ) {
10                 currMaxIndex = i;
11             }
12             while(!ascendingStack.isEmpty() && nums[ascendingStack.peek()] > nums[i]) {
13                 startIndex = Math.min(startIndex, ascendingStack.pop());  // unsorted chunk
14                 endIndex = -1;
15             }
16             ascendingStack.push(currMaxIndex);
17             if(startIndex != nums.length && endIndex == -1) {
18                 endIndex = i;  // the end of unsorted chunk: the current index i
19             }
20         }
21
22         if(startIndex == nums.length) {
23             return 0;   // the array is sorted
24         }
25
26         return endIndex - startIndex + 1;
27     }
28 }

Idea 2. The boundary of unsorted subarray is determined by the leftmost and rightmost elements not in the correct position(the sorted position). Borrow the idea from selection sort, for any pair of integeras (0 < i < j < nums.length), if num[i] > nums[j],  this pair will get swapped to get the right position for the sorted array, since we only require the bounday, there is no need to sort it, just note down the index of elements which mark the boundary of the unsorted subarray. Hence, out of all pairs, the leftmost index i not at it‘s correct position is the left boundary, the rightmost index j is the right boundary.

Time complexity: O(n2)

Space complexity: O(1)

 1 class Solution {
 2     public int findUnsortedSubarray(int[] nums) {
 3        int startIndex = nums.length;
 4        int endIndex = -1;
 5
 6        for(int i = 0; i < nums.length; ++i) {
 7            for(int j = i; j < nums.length; ++j) {
 8                if(nums[i] > nums[j]) {
 9                    startIndex = Math.min(startIndex, i);
10                    endIndex = Math.max(endIndex, j);
11                }
12            }
13        }
14
15        if(startIndex == nums.length) {
16            return 0;
17        }
18
19        return endIndex - startIndex + 1;
20     }
21 }

Idea 3. Comparing with the correct position in the sorted array, mark down the leftmost index and rightmost index different from the sorted position.

Time complexity: O(nlogn)

Space complexity: O(n)

 1 class Solution {
 2     public int findUnsortedSubarray(int[] nums) {
 3         int[] numsSorted = Arrays.copyOf(nums, nums.length);
 4
 5         Arrays.sort(numsSorted);
 6
 7         int startIndex = nums.length;
 8         int endIndex = -1;
 9         for(int i = 0; i < nums.length; ++i) {
10             if(nums[i] != numsSorted[i]) {
11                 startIndex = Math.min(startIndex, i);
12                 endIndex = Math.max(endIndex, i);
13             }
14         }
15
16         if(startIndex == nums.length) {
17             return 0;
18         }
19
20         return endIndex - startIndex + 1;
21     }
22 }

Idea 4. The correct position of the minimum element in the unsorted subarray determins the left boundary, the correct position of the maximum element in the unsorted subarray determins the right boundary. Two steps: 1. Find the unsorted subarray 2. find the minimum and maximum

a. stack in ascending order for min, in descending order for maxmum

While traversing over the nums array starting from the begining, pushing elements over the stack if in asecending order, otherwise in a falling slope(unsorted subarray), an element nums[j] smaller than the element on the top of the stack, poping elements in the stack until the elemnts on the top is equal or smaller than nums[j], the last poped element is the correct position for nums[j]. For all the nums[j] not in correct position, the minmum of the correct positions determins the left boundary.

Time complexity: O(n)

Space complexity: O(n)

 1 class Solution {
 2     public int findUnsortedSubarray(int[] nums) {
 3         Deque<Integer> indexStack = new LinkedList<>();
 4
 5         int startIndex = nums.length;
 6         int endIndex = -1;
 7         for(int i = 0; i < nums.length; ++i) {
 8             while(!indexStack.isEmpty() && nums[indexStack.peek()] > nums[i]) {
 9                 startIndex = Math.min(startIndex, indexStack.pop());
10             }
11             indexStack.push(i);
12         }
13
14         for(int i = nums.length-1; i >= 0; --i) {
15             while(!indexStack.isEmpty() && nums[i] > nums[indexStack.peek()]) {
16                 endIndex = Math.max(endIndex, indexStack.pop());
17             }
18             indexStack.push(i);
19         }
20
21         if(startIndex == nums.length) {
22             return 0;
23         }
24
25         return endIndex - startIndex + 1;
26     }
27 }

b. without extra space, rising slope starting from the begining, falling slope staring from the end

Time complexity: O(n)

Space complexity: O(1)

C1 class Solution {
 2     public int findUnsortedSubarray(int[] nums) {
 3         int startIndex = 0;
 4
 5         while(startIndex+1 < nums.length && nums[startIndex] <= nums[startIndex+1]) {
 6             ++startIndex;
 7         }
 8
 9         if(startIndex == nums.length-1) {
10             return 0;
11         }
12
13         int minItem = nums[startIndex+1];
14         for(int i = startIndex+1; i < nums.length; ++i) {
15             minItem = Math.min(minItem, nums[i]);
16         }
17
18         // nums[0..startIndex] is sorted,
19         // the correct position is the index of the first element bigger than minItem
20         // from 0 to startIndex (left to right)
21         for(int i = 0; i <= startIndex; ++i) {
22             if(nums[i] > minItem) {
23                 startIndex = i;
24                 break;
25             }
26         }
27
28         int endIndex = nums.length-1;
29         while(endIndex-1 >= 0 && nums[endIndex-1] <= nums[endIndex]) {
30             --endIndex;
31         }
32
33         int maxItem = nums[endIndex-1];
34         for(int i = endIndex-1; i >= 0; --i) {
35             maxItem = Math.max(maxItem, nums[i]);
36         }
37
38         // nums[endIndex, nums.length-1] is sorted
39         // the correct position of the index of the first element smaller than maxItem
40         // from nums.length-1 to endIndex (right to left)
41         for(int i = nums.length-1; i>= endIndex; --i) {
42             if(nums[i] < maxItem) {
43                 endIndex = i;
44                 break;
45             }
46         }
47
48         return endIndex - startIndex + 1;
49     }
50 }

Find the first unsorted subarray and the minimum element can be combine in one loop to make code more concise.

 1 class Solution {
 2     public int findUnsortedSubarray(int[] nums) {
 3         int minItem = Integer.MAX_VALUE;
 4
 5         boolean isSorted = true;
 6         for(int i = 1; i < nums.length; ++i){
 7             if(nums[i-1] > nums[i]) {
 8                 isSorted = false;
 9             }
10
11             if(!isSorted) {
12                 minItem = Math.min(minItem, nums[i]);
13             }
14         }
15
16         if(isSorted) {
17             return 0;
18         }
19
20         int startIndex = 0;
21         for(; startIndex < nums.length; ++startIndex) {
22             if(nums[startIndex] > minItem) {
23                 break;
24             }
25         }
26
27         int maxItem = Integer.MIN_VALUE;
28         isSorted = true;
29         for(int i = nums.length-2; i >= 0; --i) {
30             if(nums[i] > nums[i+1]) {
31                 isSorted = false;
32             }
33
34             if(!isSorted) {
35                 maxItem = Math.max(maxItem, nums[i]);
36             }
37         }
38
39         int endIndex = nums.length-1;
40         for(;endIndex >= 0; --endIndex) {
41             if(nums[endIndex] < maxItem) {
42                 break;
43             }
44         }
45
46         return endIndex - startIndex + 1;
47     }
48 }

原文地址:https://www.cnblogs.com/taste-it-own-it-love-it/p/10393642.html

时间: 2024-08-29 15:34:31

Shortest Unsorted Continuous Subarray LT581的相关文章

LeetCode 581. 最短无序连续子数组(Shortest Unsorted Continuous Subarray)

581. 最短无序连续子数组 581. Shortest Unsorted Continuous Subarray 题目描述 给定一个整型数组,你需要寻找一个连续的子数组,如果对这个子数组进行升序排序,那么整个数组都会变为升序排序. 你找到的子数组应是最短的,请输出它的长度. LeetCode581. Shortest Unsorted Continuous Subarray 示例 1: 输入: [2, 6, 4, 8, 10, 9, 15] 输出: 5 解释: 你只需要对 [6, 4, 8,

581. Shortest Unsorted Continuous Subarray 最短未排序的连续子阵列

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. E

[LeetCode] Shortest Unsorted Continuous Subarray 最短无序连续子数组

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. E

LeetCode - 581. Shortest Unsorted Continuous Subarray

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. E

Shortest Unsorted Continuous Subarray

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. E

581. Shortest Unsorted Continuous Subarray (LeetCode)

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

581. Shortest Unsorted Continuous Subarray

1 static int wing=[]() 2 { 3 std::ios::sync_with_stdio(false); 4 cin.tie(NULL); 5 return 0; 6 }(); 7 8 class Solution 9 { 10 public: 11 int findUnsortedSubarray(vector<int>& nums) 12 { 13 int sz=nums.size(); 14 int beg=-1,end=-2,maxele=nums[0],m

LeetCode算法题-Shortest Unsorted Continuous Subarray(Java实现)

这是悦乐书的第267次更新,第281篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第134题(顺位题号是581).给定一个整数数组,找到一个连续的子数组,按升序对该子数组进行排序,使得整个数组也按升序排序.找到最短的无序连续子数组并输出其长度.例如: 输入:[2,6,4,8,10,9,15] 输出:5 说明:按升序对[6,4,8,10,9]子数组进行排序,以使整个数组按升序排序. 注意: 数组的长度在[1,100]范围内. 数组可能包含重复项,因此这里的升序表示<=

Continuous Subarray Sum

Given an integer array, find a continuous subarray where the sum of numbers is the biggest. Your code should return the index of the first number and the index of the last number. (If their are duplicate answer, return anyone) 和Maximum Subarray的差别在于仅