题目
给你一个二维整数数组 envelopes ,其中 envelopes[i] = [wi, hi] ,表示第 i 个信封的宽度和高度。
当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。
请计算 最多能有多少个 信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。
tga:动态规划
二分查找
题解
学习自官方题解
class Solution {
public:
int maxEnvelopes(vector<vector<int>>& envelopes) {
int n=envelopes.size();
if(n==0)
return 0;
sort(envelopes.begin(),envelopes.end(),[](const auto& a,const auto& b){
return a[0]<b[0] || ((a[0]==b[0])&&a[1]>b[1]);
});
vector<int> f(n,1); //记录最长严格单调递增子序列
for(int i=1;i<n;i++){
for(int j=0;j<i;j++){
if(envelopes[i][1]>envelopes[j][1]){
f[i]=max(f[i],f[j]+1);
}
}
}
return *max_element(f.begin(),f.end());
}
};
- 首先从一维的角度进行简化思考:
如果仅考虑h,且从题目角度需要满足$h_i < h_j$,才可以进行“装入”的操作 - 但是数据可能存在等于关系,再次简化思考:
假设所有数据都只有不等关系,则对一维上的俄罗斯套娃信封问题,只需求最长递增子序列 - 回到本题,我们着手于最长递增子序列,且排除数据等于关系的影响
即:我们必须要保证对于每一种 w 值,我们最多只能选择 1 个信封。
因此我们就可以得到解决本题需要的方法:
- 首先我们将所有的信封按照 w 值第一关键字升序、h 值第二关键字降序进行排序;
- 随后我们就可以忽略 w维度,求出 h 维度的最长严格递增子序列,其长度即为答案。
第二关键字的降序,导致求解最长严格递增子序列时可以排除相等数据的影响
[1,4] [1,3] [1,2] [1,1] [2,4]的最长严格递增子序列为2
- 二维的最长严格单调递增子序列
vector<int> f(n,1); //记录最长严格单调递增子序列
for(int i=1;i<n;i++){
for(int j=0;j<i;j++){
if(envelopes[i][1]>envelopes[j][1]){
f[i]=max(f[i],f[j]+1);
}
}
}
从0到i的数据,f中记录着其最长调度递增子序列长度
f[i]=max(f[i],f[j]+1) f[i]满足题目关系中的递增于f[j]