581. Shortest Unsorted Continuous Subarray
问题:
求数列中最小的未排序子数列(即,如果将此子数列排序后,整个数列则成为有序数列)
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.
Input: [2, 4, 6, 3, 14, 10, 13, 15] Output: 6 Explanation: You need to sort [4, 6, 3, 14, 10, 13] in ascending order to make the whole array sorted in ascending order.
解法一:sort+对比法
1. 首先copy到新的数列,并sort
[2, 4, 6, 3, 14, 10, 13, 15] -> [2, 3, 4, 6, 10, 13, 14, 15] 0 1 2 3 4 5 6 7 ^ ^ Start End
2. 顺次对比两个数列
3. 得到两个数列不相等元素的Start和End
则所求长度为End-Start+1
代码参考:
1 class Solution { 2 public: 3 int findUnsortedSubarray(vector<int>& nums) { 4 vector <int> sortednums(nums); 5 sort(sortednums.begin(), sortednums.end()); 6 int start = nums.size()-1, end = 0; 7 for(int i = 0; i<nums.size(); i++){ 8 if(sortednums[i]!=nums[i]){ 9 start = min(start, i); 10 end = max(end, i); 11 } 12 } 13 return (end-start > 0? end-start+1:0); 14 } 15 };
解法二:
例如:
[2, 4, 6, 3, 14, 10, 13, 15] 0 1 2 3 4 5 6 7 ^ ^
1.先从两端取得顺序排列的[0~i]和[j~end]
[2,4,6] -> i=2 (0~i 递增) [10,13,15] -> j=5 (j~end递增)
2.对于余下的数列 [3,14],取得最大值,和最小值
min = 3 max = 14
3.使用2中取得最大值最小值,向两侧推移,找到 向左<min 和 向右>max的边界【i,j】。
[2,4,6] -> i=0 (2<3<4) ^ [10,13,15] -> j=7 (13<14<15) ^
则,[4,6,....,10,13]为所求最小子数列,长度为:j-i-1=7-0-1=6
代码参考:
1 class Solution { 2 public: 3 int findUnsortedSubarray(vector<int>& nums) { 4 int i=0, j=nums.size()-1; 5 while(i<nums.size()-1){ 6 if(nums[i]>nums[i+1])break; 7 i++; 8 } 9 if(i>=j) return 0; 10 while(j>0){ 11 if(nums[j]<nums[j-1])break; 12 j--; 13 } 14 int maxN=INT_MIN, minN=INT_MAX; 15 for(int k=i; k<=j; k++){ 16 maxN=max(maxN, nums[k]); 17 minN=min(minN, nums[k]); 18 } 19 while(i>=0){ 20 if(nums[i]>minN)i--; 21 else {break;} 22 } 23 while(j<nums.size()){ 24 if(nums[j]<maxN)j++; 25 else {break;} 26 } 27 return j-i-1; 28 } 29 };