力扣技巧之动态规划力扣354:俄罗斯套娃信封问题C++

Posted The Gao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了力扣技巧之动态规划力扣354:俄罗斯套娃信封问题C++相关的知识,希望对你有一定的参考价值。

原题

给你一个二维整数数组 envelopes ,其中 envelopes[i] = [wi, hi] ,表示第 i 个信封的宽度和高度。

当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。

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

注意:不允许旋转信封。

分析

这道题在LeetCode平台上的难度为hard。

首先,我们看,如何能够让一个信封嵌套到另一个信封中,当A信封的宽和高都大于B信封的宽和高时,那么B信封就可以嵌入A信封中。

如果信封只有一个属性,以宽为例,且嵌套的条件只有一个要求,即A信封的宽大于B信封的宽时,B信封即可嵌入A信封。那么这道题其实与【力扣技巧之动态规划】力扣300:最大递增子序列【C++】是一样的解题方法。给定的是一个带有各信封宽度的数组,而能够嵌套的条件是宽度大于前者,即宽度是递增的,那么计算最多能有多少个信封能组成一组“俄罗斯套娃”信封实际上就是在宽度数组中计算最大递增子序列的长度。

如果上述能够理解的话,那么我们再来看题目。对于一个信封,它的属性不是一维的了,而是一个二维数组,包括宽和高,因此与最大递增子序列不完全一样的。

如果要满足B信封能够嵌入A信封,要求A信封的宽和高都要分别大于B信封的宽和高,即宽和高都要是递增的,才能够完成信封的嵌套。那么我们不妨先完成对其中一个属性的递增排序,以宽为例,将所有信封按照宽度升序排列。

此时我们将高度看成一个一维数组,求高度数组中最大递增子序列的长度,不就是最多能有多少个信封能组成一组“俄罗斯套娃”信封了吗?

如果出现两个信封的宽度一致时,注意要再按照高度降序排列。为了帮助理解,我们举这样一个例子,比如两个信封[6,4]、[6,7],这两个信封不能完成嵌套。但是如果高度是升序排列的话,只考虑高度的情况下,其实这两个信封在代码中会被处理成是可以嵌套的,会对结果产生影响。如果按照高度降序排列,则可以避免这种影响。

代码

class Solution {
public:
    int maxEnvelopes(vector<vector<int>>& envelopes) {
        int size=envelopes.size();
        if(size==0||size==1)return size;
        /*这里的排序处理对本题的求解至关重要*/
        sort(envelopes.begin(),envelopes.end(),mycompare);
        /*动态规划过程与力扣300的思路完全一致*/
        vector<int>dp(size,1);
        int maxsize=INT_MIN;
        for(int i=0;i<size;i++){
            for(int j=0;j<i;j++){
                if(envelopes[i][1]>envelopes[j][1]){
                    dp[i]=max(dp[i],1+dp[j]);
                }
            }
        }
        for(int i:dp)maxsize=max(maxsize,i);
        return maxsize;
    }
    /*排序规则:按宽度升序,宽度相等时按高度降序*/
    static bool mycompare(vector<int>a,vector<int>b){
        return a[0]==b[0]?a[1]>b[1]:b[0]>a[0];
    }
};

以上是关于力扣技巧之动态规划力扣354:俄罗斯套娃信封问题C++的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 354. 俄罗斯套娃信封问题

LeetCode 354. 俄罗斯套娃信封问题

力扣技巧之动态规划力扣322:零钱兑换C++

力扣技巧之动态规划力扣300:最大递增子序列C++

力扣技巧之动态规划力扣53:最大子数组和C++

数据结构与算法之深入解析“俄罗斯套娃信封问题”的求解思路与算法示例