581. Shortest Unsorted Continuous Subarray(最短無序連續子數組)

581. 最短無序連續子數組

給定一個整數數組,你需要尋找一個連續的子數組,如果對這個子數組進行升序排序,那麼整個數組都會變爲升序排序。

你找到的子數組應是最短的,請輸出它的長度。

示例 1:

輸入: [2, 6, 4, 8, 10, 9, 15]
輸出: 5
解釋: 你只需要對 [6, 4, 8, 10, 9] 進行升序排序,那麼整個表都會變爲升序排序。

說明 :

  1. 輸入的數組長度範圍在 [1, 10,000]。
  2. 輸入的數組可能包含重複元素 ,所以升序的意思是<=。

解法一

//時間複雜度O(nlogn), 空間複雜度O(n)
class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
        vector<int> temp(nums);
        sort(temp.begin(), temp.end());
        int i = 0, j = nums.size() - 1;
        while (i < j) {
            if(nums[i] != temp[i] && nums[j] != temp[j]) break;
            if(nums[i] == temp[i]) i++;
            if(nums[j] == temp[j]) j--;
        }
        return i >= j ? 0 : j - i + 1;
    }
};

解法二

//時間複雜度O(n), 空間複雜度O(1)
class Solution {
public:
    int findUnsortedSubarray(vector<int>& nums) {
        int len = nums.size();
        int max = nums[0], min = nums[len - 1];
        int start = 1, end = 0;
        for(int i = 1; i < len; i++) {
            if(nums[i] >= max) max = nums[i];//等於號不可少
            else end = i;//當max > nums[i]
            if(nums[len - 1 - i] <= min) min = nums[len - 1 - i];
            else start = len - 1 - i;
        }
        return end - start + 1;
    }
};

思路:

解法一,先構造一個相同的數組,排序,再從兩端開始向中間遍歷,比較與原數組不同的地方。

解法二,這個解法確實厲害。一開始有些難理解,建議找個例子人腦調試一下就懂了。

循環體內從左、右兩端開始同時遍歷,只看其中從左至右這一個方向的話,這個循環所做的,就是就標記end向右推到最終合適的位置(“合適”是指該標記右側所有元素都大於其左側元素,且右側元素爲增序);同理,反向是把標記start向左推。最終得到一個不合法序列的範圍,返回其長度。

要注意的是,對於一個從小到大的有序序列,它不會修改兩個標記,這時應該讓其返回1,這是我們讓start = 1, end = 0的原因。

2019/06/03 21:58
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章