力扣技巧之动态规划力扣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++的主要内容,如果未能解决你的问题,请参考以下文章