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.
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.
建立另一个数组,sort
比较新数组与原数组,从前到后,从后到前,记录第一个不一样的数字为start,end。最后答案长度为end-start+1。
1 public int findUnsortedSubarray(int[] nums) { 2 int[] arr = new int[nums.length]; 3 System.arraycopy(nums, 0, arr, 0, nums.length); 4 Arrays.sort(arr); 5 6 int start = 0; 7 int end = nums.length - 1; 8 9 while (start < nums.length && nums[start] == arr[start]) { 10 start++; 11 } 12 while (end > 0 && nums[end] == arr[end]) { 13 end--; 14 } 15 if (start == nums.length) { 16 return 0; 17 } 18 return end - start + 1; 19 }
方法2: 优化
扫一遍数组,update end为最后一个降的位置,start为从右到左最后一个升的位置。最后答案长度为end-start+1。
做法:
有currentLeft,currentRight变量,记录当前从左到右,从右到左应该有的大小,每一个新的位置,先更新变量值,再比较如果不符合正确趋势,
更新start或end。
e.g. [2,6,4,8,10,9,15]
1.
currentLeft=2 (from left to right until current idx, maximal val)
currentRight=15 (from right to left until current idx, minimal val)
start = -1
end = -2
2.
from i = 1, for each i, (同时看 nums.length - i - 1)
1. update currentLeft, currentRight,
currentLeft = Math.max(currentLeft, nums[i]) 从左到右,应是上升的趋势,所以当前至少有前一个数那么大
currentRight = Math.min(currentRight, nums[nums.length - i - 1]) 从右到左,应是下降的趋势,所以当前比后一个数小或相等
2. compare current numbers (nums[i], nums[nums.length - i - 1]) with currentLeft, currentRight, 如果不满足上升/下降的趋势,update min, max
最后,end: 从左到右 最后一个降的位置,start: 从右到左 第一个升的位置
i=1 cl=6 cr=9 ok (其中 cl = Math.max(cl, nums[i]) )
i=2 cl=6 cr=9 cl>4 end = 2 cr<10 start=4
i=3 cl=8 cr=8 ok
i=4 cl=10 cr=4 ok
i=5 cl=10 cr=4 cl>8 end=5 cr<6 start=1
i=6 cl=15 cr=2 ok
[2,6,4,8,10,9,15]
st e -> e - start = 5
1 public int findUnsortedSubarray(int[] nums) { 2 int currentLeft = nums[0]; 3 int currentRight = nums[nums.length - 1]; 4 int start = -1; 5 int end = -2; 6 7 for (int i = 1; i < nums.length; i++) { 8 currentLeft = Math.max(currentLeft, nums[i]); 9 currentRight = Math.min(currentRight, nums[nums.length - i - 1]); 10 if (nums[i] < currentLeft) { 11 end = i; 12 } 13 if (nums[nums.length - i - 1] > currentRight) { 14 start = nums.length - i - 1; 15 } 16 } 17 return end - start + 1; 18 }