300. 最長上升子序列--LeeCode刷題(誤用單調棧,反思)

心情:哇!最近刷題越來越不順心了,這道題不難吧!但是卻花了很長時間…

題目描述:

給定一個無序的整數數組,找到其中最長上升子序列的長度。

示例:

輸入: [10,9,2,5,3,7,101,18]
輸出: 4
解釋: 最長的上升子序列是 [2,3,7,101],它的長度是 4。

自己的想法:

我看到這道題首先理解題目的意思:在當前位置的前面,有多少數比當前數字小,且這些小的數字逐漸遞增,而我想到的第一個方法是用單調棧!!!因爲都是按順序,而且找當前位置之前小於它的數

之後興致勃勃打完代碼,發現不對,後來回顧了一下單調棧,發現單調棧所解決的問題有一個特點,就是單調棧有一個截斷性連續性的問題。

打幾個比方
(截圖來自於https://blog.csdn.net/lucky52529/article/details/89155694
在這裏插入圖片描述

它相當於找當前位置之後比它小的值,但是要滿足兩個條件,第一連續的,第二,當遇到第一個比當前位置大的值,那麼當前位置就能出了最終結果!

2.第二個例子

在這裏插入圖片描述
這題求最大的矩形面積:首先維護的是個單調遞減的棧(棧內0~n爲單調遞增),也就是如果遇到第一個小於棧頂的棧時,就要更新要出棧(即大於當前值)裏面的元素的最終值,最終值爲棧元素高度乘距離。而這個值也是最終值!!!

回到本題
這題求的問題,子集不一定連續!!!,故不能這樣求。

解題方法:

1.暴力(略)

2.插入法(其他的說的爲二分法)

首先維護一個子集,在nums中每取一個元素加入到子集中(lower_bound()),當:
1.當前元素大於子集元素的最大數時,插入到隊尾
2.當不是隊尾,那說明子集裏面有一個元素剛好大於等於它,正常思維肯定想,直接插入在前面,但是不行!!!而是取代這個數字,原因?因爲當前位置後面的元素是在當前 i 之前的元素,意思是nums[i] 並不是大於nums[i]的數的子集,所以只能代替,那爲啥要代替,因爲爲了使有順序的數字更多,你得保證子集之間的間距越小
好吧我說不清楚,但是實際上自己可以體會的!!!上代碼就很清楚了:

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        vector<int> st;
        for(int i=0;i<nums.size();i++){
            auto it=lower_bound(st.begin(),st.end(),nums[i]);
            if(it==st.end()) st.push_back(nums[i]);
            else *it=nums[i];
        }
        return st.size();
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章