最长上升子序列

300.最长上升子序列

给定一个无序的正数数组,找到其中最长上升子序列的长度

示例

输入:[10,9,2,5,3,7,101,18]

输出:4

解释:最长的上升子序列是 [2,3,7,101],它的长度是 4

思路

动态规划,\(dp[i]\)表示以\(nums[i]\)结尾的最长上升子序列长度

\[nums[i]>nums[j] ==> dp[i]=max(dp[j])+1 \]

代码

class Solution {
public:
    int lengthOfLIS(vector<int>& nums) {
        //dp[i]表示以数字i结尾的最长上升子序列长度
        vector<int> dp(nums.size(),0); 
        if(nums.empty()) return 0;
        for(int i=0;i<nums.size();i++)
        {
            dp[i]=1;
            for(int j=0;j<i;j++)
            {
                if(nums[i]>nums[j])
                    dp[i]=max(dp[i],dp[j]+1);
            }
        }
        return *max_element(dp.begin(),dp.end());
    }
};

673.最长递增子序列的个数

给定一个未排序的整数数组,找到最长递增子序列的个数

示例

输入:[1,3,5,4,7]

输出:2

解释:有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, 3, 5, 7]

思路

动态规划,相比于第一题,新增一个\(counter[i]\)表示以\(nums[i]\)结尾的最长递增子序列的组合数量

  • 总体需满足\(nums[i]>nums[j]\)

  • 若\(dp[j]+1>dp[i]\),说明第一次找到以\(nums[i]\)为结尾的最长递增子序列,长度为\(dp[j]+1\),进而可以推出\(counter[i]==counter[j]\)

  • 若\(dp[j]+1==dp[i]\),说明这个长度已经找到过一次,\(counter[i]+=counter[j]\)

代码

class Solution
{
public:

    int findNumberOfLIS(vector<int> &nums)
    {
        vector<int> dp(nums.size(), 0);
        vector<int> counter(nums.size(), 1);
        if (nums.empty()) return 0;
        for (int i = 0; i < nums.size(); i++)
        {
            dp[i] = 1;
            for (int j = 0; j < i; j++)
            {
                if (nums[i] > nums[j])
                {
                    if (dp[j] + 1 > dp[i])
                    {
                        dp[i] = max(dp[i], dp[j] + 1);
                        counter[i] = counter[j];
                    } else if (dp[j] + 1 == dp[i])
                        counter[i] += counter[j];
                }
            }
        }
        int res = 0;
        int length = *max_element(dp.begin(), dp.end());
        for (int i = 0; i < dp.size(); ++i)
        {
            if (dp[i] == length)
                res += counter[i];
        }
        return res;
    }
};
posted @ 2020-09-03 10:13  周颖  阅读(38)  评论(0)    收藏  举报