leetcode_334.遞增的三元子序列

題目

給定一個未排序的數組,判斷這個數組中是否存在長度爲 3 的遞增子序列。

數學表達式如下:

如果存在這樣的 i, j, k, 且滿足 0 ≤ i < j < k ≤ n-1,
使得 arr[i] < arr[j] < arr[k],返回 true ; 否則返回 false 。

說明: 要求算法的時間複雜度爲 O(n),空間複雜度爲 O(1) 。

示例 1:

輸入: [1,2,3,4,5]
輸出: true

示例 2:

輸入: [5,4,3,2,1]
輸出: false

思路

首先,新建兩個變量 small 和 mid ,分別用來保存題目要我們求的長度爲 3 的遞增子序列的最小值中間值

接着,我們遍歷數組,每遇到一個數字,我們將它和 small 和 mid 相比,

  • 若小於等於 small ,則替換 small;
  • 否則,若小於等於 mid,則替換 mid;
  • 否則,若大於 mid,則說明我們找到了長度爲 3 的遞增數組!(已確認了第一、二個數,第三個數一但確定,則大勢定矣

求解過程中有個問題:

當已經找到了長度爲 2 的遞增序列,這時又來了一個比 small 還小的數字,爲什麼可以直接替換 small 呢,這樣 small 和 mid 在原數組中並不是按照索引遞增的關係呀?
例如: 檢測完了第一二號元素,此時small = 3, mid = 5, 這時檢測到了一個 “2”, 也就是說要用三號“2”將一號“1”替換,此時【small = 三號“2” mid = 二號“5”】,與題意不符。

爲了解釋這個問題,我們假如當前的 small 和 mid 爲 [3, 5],這時又來了個 1。假如我們不將 small 替換爲 1,那麼,當下一個數字是 2,後面再接上一個 3 的時候,我們就沒有辦法發現這個 [1,2,3] 的遞增數組了!也就是說,我們替換最小值,是爲了後續能夠更好地更新中間值!

且,即使我們更新了 small ,這個 small 在 mid 後面,沒有嚴格遵守遞增順序,但它卻可以證明,有一個比 small 大比 mid 小的值出現在 mid 之前。因此,當後續出現比 mid 大的值的時候,我們一樣可以通過當前 small 和 mid 推斷的確存在着長度爲 3 的遞增序列。 所以,這樣的替換並不會干擾我們後續的計算!

前兩段有點拗口,但是注意一句話可以迎刃而解:

有一個比 small 大比 mid 小的值出現在 mid 之前

這是保證程序原理不出錯的關鍵。

代碼如下:

class Solution {
public:
    bool increasingTriplet(vector<int>& nums) {
        int len = nums.size();
        if (len < 3) return false;
        int small = INT_MAX, mid = INT_MAX;
        for (auto num : nums) { // 定義num變量,將它的指針順次指向nums數組的每個元素(關於auto,百度一下,你就知道)
        	//接下來三行是程序主體
            if(num <= small) small = num;
            else if(num <= mid) mid = num; 
            else if(num > mid) return true; //發現了第三個數,大功告成
        }
        return false;    
    }
};

點個贊再走唄~

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