300. Longest Increasing Subsequence

题目:

Given an integer array nums, return the length of the longest strictly increasing subsequence.

subsequence is a sequence that can be derived from an array by deleting some or no elements without changing the order of the remaining elements. For example, [3,6,2,7] is a subsequence of the array [0,3,1,6,2,2,7].

 

Example 1:

Input: nums = [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.

Example 2:

Input: nums = [0,1,0,3,2,3]
Output: 4

Example 3:

Input: nums = [7,7,7,7,7,7,7]
Output: 1

 

Constraints:

  • 1 <= nums.length <= 2500
  • -104 <= nums[i] <= 104

 

Follow up:

  • Could you come up with the O(n2) solution?
  • Could you improve it to O(n log(n)) time complexity?

 

思路1:

题意是找出最长的subsequence,此处字符列指可以不连续,但是不能破坏顺序。首先讨论O(n^{2})的方法,用额外的vector<int>,长度与原数组相等,作为DP数组,假设叫dp。dp[i]表示到nums[i]为止最长的子序列,因此只要遍历dp中[0, i),找到最大值,加1即可作为dp[i]的备选项。状态转移方程为dp[i]=max(dp[i],dp[j]+1)), 0\leq j<i。。对于dp的初始化,所有格子都是1,因为自身可以作为子序列,最短至少为1。

 

代码1:

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n=nums.size();
        if(n==0)
            return 0;
        vector<int> dp(n,1);
        int ans=1;
        for(int i=1;i<n;i++)
        {
            for(int j=0;j<i;j++)
            {
                if(nums[i]>nums[j])
                    dp[i]=max(dp[i],dp[j]+1);
            }
            ans=max(ans,dp[i]);
        }
        return ans;
    }
};

 

思路2:

Follow up问的是O(nlog(n)))复杂度,这里看到对数级比较容易想到二分法。首先建立一个空数组res,用来储存到目前为止最长的subsequence。遍历nums,对于每个数,用lower_bound去寻找它应该在res里的位置,如果找到的是res.end(),说明当前的数字比res里面都要大,可以成为新的tail,把当前数加入res,否则的话说明当前subsequence里有比这个大的元素可以被替换。这一步其实主要是为了替换当前res里面的最后一个值,来控制之后可以加入的元素的最小值。其实它也会替换前面的值,比如例子数组[10,9,2,5,3,7,1,101,18],当遍历到1时,res里是[2, 3, 7],然后1会替换2,虽然这破坏了顺序,但是其实这无关紧要,我们最后关心的是res的长度,而不是内容。因此这个替换最重要的是替换最后一个位置如[9,2,3]遍历到2时,res里是[9],此时res变成[2],则后面的3可以被加入进res。但是又不能仅仅只检查res的最后一个数,因为这样会导致最后一位从大小上出错。比如[4,10,4,3,8,9],那么遍历到4时,res是[4,10],如果按照大小计算,10会被4替换,会导致错误。

 

代码2:

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        int n=nums.size();
        vector<int> res;
        for(auto i:nums)
        {
            auto itr=lower_bound(res.begin(),res.end(),i);
            if(itr==res.end())
                res.push_back(i);
            else
                *itr=i;
        }
        return res.size();
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值