zoukankan      html  css  js  c++  java
  • dp-最长子序列问题

    基本思想:

    300. 最长上升子序列 M

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

    通用方法:

    class Solution {
    public:
        int lengthOfLIS(vector<int>& nums) {
            int n = nums.size();
            if (n == 0) return 0;
            vector<int> dp(n,1);
            for(int i = 0; i < n; i++){
                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());
        }
    };

    用二分查找,可以将复杂度下降到 NlogN

    定义一个 tails 数组,其中 tails[i] 存储长度为 i + 1 的最长递增子序列的最后一个元素。对于一个元素 x,

    • 如果它大于 tails 数组所有的值,那么把它添加到 tails 后面,表示最长递增子序列长度加 1;
    • 如果 tails[i-1] < x <= tails[i],那么更新 tails[i] = x。
    class Solution {
    public:
        int lengthOfLIS(vector<int>& nums) {
            int n = nums.size();
            if (n == 0) return 0;
            vector<int> tail(n);
            int len = 0;
            for(int i = 0; i < n; i++){
                int l = 0,r = len;
                while(l < r){
                    int m = l + (r-l)/2;
              // nums[i]插入左边
    if(tail[m] >= nums[i]) r = m;
              // nums[i]插入右边
    else l = m+1; } tail[l] = nums[i];
            //如果大于所有的数
    if(l == len) len++; } return len; } };

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

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

    在上一题的基础上增加一个记录数组:

    class Solution {
    public:
        int findNumberOfLIS(vector<int>& nums) {
            int n = nums.size();
            if(n == 0) return 0;
            vector<int> dp(n,1),p(n,1);//注意初始化为1
            for(int i = 0; i < n; i++)
                for(int j = 0; j <i; j++){
                    if(nums[i] > nums[j])//判断条件
                        if(dp[i] < dp[j]+1){
                            dp[i] = dp[j]+1;
                            p[i] = p[j];
                        }
                        else if(dp[i] == dp[j]+1)//相等等于两个支路相加
                            p[i]+=p[j];
                }
            int mm = *max_element(dp.begin(),dp.end());
            int res = 0;
            for(int i = 0; i < n; i++)
                if(dp[i] == mm) res+= p[i];
            return res;
        }
    };

    646. 最长数对链

    给出 n 个数对。 在每一个数对中,第一个数字总是比第二个数字小。

    现在,我们定义一种跟随关系,当且仅当 b < c 时,数对(c, d) 才可以跟在 (a, b) 后面。我们用这种形式来构造一个数对链。

    给定一个对数集合,找出能够形成的最长数对链的长度。你不需要用到所有的数对,你可以以任何顺序选择其中的一些数对来构造。

    通用方法:

    class Solution {
    public:
        int findLongestChain(vector<vector<int>>& pairs) {
            sort(pairs.begin(),pairs.end());
            int n = pairs.size();
            vector<int> dp(n,1);
            for(int i = 0; i <n; i++)
                for(int j = 0; j < i; j++)
                    if(pairs[i][0] > pairs[j][1])
                        dp[i] = max(dp[i],dp[j]+1);
            return *max_element(dp.begin(),dp.end());
        }
    };

    376. 摆动序列

    如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。

    通用方法:

    class Solution {
    public:
        int wiggleMaxLength(vector<int>& nums) {
            int n = nums.size();
            if(n == 0) return 0;
            if( n <= 2) return 1;
            vector<int> up(n,1),down(n,1);
            for(int i = 1; i <n; i++){
                for(int j = 0;j < i; j++)
                    if(nums[i] > nums[j])
                        up[i] = max(up[i],down[j]+1);
                    else if(nums[i] < nums[j])
                        down[i] = max(down[i],up[j]+1);
            }
            return max(up[n-1],down[n-1]);
        }
    };

    354. 俄罗斯套娃信封问题

    给定一些标记了宽度和高度的信封,宽度和高度以整数对形式 (w, h) 出现。当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。

    请计算最多能有多少个信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。

    通用方法:

    class Solution {
    public:
        int maxEnvelopes(vector<vector<int>>& envelopes) {
            int n = envelopes.size();
            if( n== 0) return 0;
            sort(envelopes.begin(),envelopes.end());
            vector<int> dp(n,1);
            for(int i = 0; i < n; i++)
                for(int j = 0; j < i; j++){
                    if(envelopes[i][0] > envelopes[j][0] && envelopes[i][1] > envelopes[j][1])
                        dp[i] = max(dp[i],dp[j]+1);
                }
            return *max_element(dp.begin(),dp.end());
        }
    };
  • 相关阅读:
    【MM 】采购合同成批维护
    【FICO 汇率】汇率
    【S4 MM】S4中继续使用MB系统事务代码(转)
    【MM 交货成本】Unplanned Delivery Cost
    Tracer Deployment UVALive
    The Best Path HDU
    Artwork Gym
    PTA 银行排队问题之单队列多窗口加VIP服务 队列+模拟
    Counting Cliques HDU
    Do not pour out HDU
  • 原文地址:https://www.cnblogs.com/Aliencxl/p/12313478.html
Copyright © 2011-2022 走看看