300. Longest Increasing Subsequence

Given an unsorted array of integers, find the length of longest increasing subsequence.

For example,
Given [10, 9, 2, 5, 3, 7, 101, 18],
The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that there may be more than one LIS combination, it is only necessary for you to return the length.

Your algorithm should run in O(n2) complexity.

Follow up: Could you improve it to O(n log n) time complexity?

s思路:
1. 这题之前做过,印象深刻,以至于不能好好的思考,记忆瞬间占领大脑,大脑立马停摆,不能认真思考和看清眼前的题目了!
2. 先看o(n^2)的做法:由于是求最长,就想到了dp,而最长又是从元问题一个一个的比较得到的,所以问题又可以分解,因此更加确定用dp了。
3. 题目要求降低复杂度到o(nlgn)。好好观察发现,在做dp的时候,有很多重复,例如:当判断101的位置的最长时,如果知道此时前面最长序列为[2,3,7]那么就没有必要从头到尾一个一个的尝试,完全可以用binary search找到101的位置,如果101的位置大于最后一个位置,就+1,如果小于最后一个值,则把对应的值给修改了,长度不变,那么就免去了一个一个尝试的啰嗦,变o(n)->o(lgn)
这里写图片描述
4. 这道题妙的地方在于,用维护的最长的序列的长度作为返回值,不用专门去找这个长度,而是找出一个这样的序列,虽然最后返回的这个序列不一定是最长序列,但是其长度确实是最长的!

//方法1:dp.复杂度o(n^2)
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n=nums.size();
        if(n==0) return 0;
        vector<int> dp(n,1);
        int mxlen=1;
        for(int i=1;i<n;i++){
            for(int j=0;j<i;j++){
                int cur=nums[i]>nums[j]?dp[j]+1:1;
                dp[i]=max(dp[i],cur);
            }    
            mxlen=max(mxlen,dp[i]);
        }
        return mxlen;
    }
};

//方法2:binary search
class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n=nums.size();
        if(n==0) return 0;
        vector<int> res;
        for(int i=0;i<n;i++){
            auto it=lower_bound(res.begin(),res.end(),nums[i]);//bug:改用lower_bound,不能upper_bound
            //因为lower_bound是大于和等于val的第一个位置;upper_bound是大于val的第一个位置!
            if(it!=res.end()){
                res[it-res.begin()]=nums[i];        
            }else{
                res.push_back(nums[i]);    
            }
        }
        return res.size();
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值