【算法练习】动态规划 最长递增子序列(LIS) leetcode674/354 俄罗斯套娃信封问题

最近看labuladong的书在刷题

目录

最长连续递增子序列  leetcode674

思路:

AC代码:

二维的最长递增子序列

思路:

语法:


最长连续递增子序列  leetcode674

674. 最长连续递增序列

难度简单147收藏分享切换为英文接收动态反馈

给定一个未经排序的整数数组,找到最长且 连续递增的子序列,并返回该序列的长度。

连续递增的子序列 可以由两个下标 l 和 rl < r)确定,如果对于每个 l <= i < r,都有 nums[i] < nums[i + 1] ,那么子序列 [nums[l], nums[l + 1], ..., nums[r - 1], nums[r]] 就是连续递增子序列。

示例 1:

输入:nums = [1,3,5,4,7]
输出:3
解释:最长连续递增序列是 [1,3,5], 长度为3。
尽管 [1,3,5,7] 也是升序的子序列, 但它不是连续的,因为 5 和 7 在原数组里被 4 隔开。 

示例 2:

输入:nums = [2,2,2,2,2]
输出:1
解释:最长连续递增序列是 [2], 长度为1。

提示:

  • 0 <= nums.length <= 104
  • -109 <= nums[i] <= 109

思路:

连续子序列=子串

定义dp[i]是nums[i]结尾的最长的连续子串

多步决策:

nums[i]一定在这个连续子串中

base case: 0<=i<n dp[i]=1

if(nums[i-1]<nums[i])  -->dp[i]=dp[i-1]+1

AC代码:

int findLengthOfLCIS(vector<int>& nums) {
    int n=nums.size();
    vector<int> dp(n,1);
    for(int i=1;i<n;i++){
        if(nums[i-1]<nums[i])
            dp[i]=dp[i-1]+1;
    }
    int res=0;
    for(int i=0;i<n;i++){
        res=max(res,dp[i]);
    }
    return res;
}

二维的最长递增子序列

354. 俄罗斯套娃信封问题

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

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

说明:
不允许旋转信封。

示例:

输入: envelopes = [[5,4],[6,4],[6,7],[2,3]]
输出: 3 
解释: 最多信封的个数为 3, 组合为: [2,3] => [5,4] => [6,7]。

测试文件:leetcode_LIS_354.cpp

思路:

1、先按照w升序排序如果w相同就按照h降序排序

2、找到排序后h对应的数组的最长递增子序列(子序列非连续)

语法:

  • 用vector初始化dp数组
  1. std::vector<double> values(20);

这个容器开始时有 20 个元素,它们的默认初始值都为 0。生成容器用vector初始化dp数时,同时指定元素个数,就能够减少空间额外分配的次数,这是一个很好的习惯。

  • 使用sort对于vector分类

用法:

#inlcude <algorithm> 
sort(vector.begin(),vector.end());
  • 自定义sort中的cmp函数

static bool cmp(vector<int> a,vector<int> b){  //可以简写成 ?:;

    if(a[0]!=b[0])

        return a[0]<b[0];

    else

        return a[1]>b[1];

}

static bool cmp(vector<int> a,vector<int> b){

     return a[0]==b[0]?a[1]>b[1]:a[0]<b[0];

}

 

AC代码:

//信封嵌套问题
//最长递增子序列
int LIS(vector<int>& nums) {  //最长递增子序列
    int size=nums.size();
    int res=0;
    vector<int> dp(size,1);//dp数组表示以nums[i]结尾的最长递增子序列
    for(int i=0;i<size;i++){
        for(int j=0;j<i;j++){
            if(nums[j]<nums[i])
                dp[i]=max(dp[i],dp[j]+1);
        }
    }
    for(int i=0;i<size;i++){
        res=max(dp[i],res);
    }
    return res;
}


static bool cmp(vector<int> a,vector<int> b){  //可以简写成 ?:;
    return a[0]==b[0]?a[1]>b[1]:a[0]<b[0];
}

int maxEnvelopes(vector<vector<int>>& envelopes) {
    sort(envelopes.begin(),envelopes.end(),cmp);
    vector<int> h(envelopes.size());
    for(int i=0;i<envelopes.size();i++){
        h[i]=envelopes[i][1];
    }
    return LIS(h);
}

猜你喜欢

转载自blog.csdn.net/weixin_40760678/article/details/112970892