300. Longest Increasing Subsequence
发布日期:2021-05-04 20:03:48 浏览次数:13 分类:技术文章

本文共 1966 字,大约阅读时间需要 6 分钟。

题目:

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: 4Explanation: 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();
    }
};

上一篇:516. Longest Palindromic Subsequence
下一篇:394. Decode String

发表评论

最新留言

初次前来,多多关照!
[***.217.46.12]2025年04月01日 02时03分24秒