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();
    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章