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

二维的LIS问题

可以先看经典的LIS

354. 俄罗斯套娃信封问题

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

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

说明:
不允许旋转信封。

示例:

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

思路:将信封按宽度和高度从小到大排序,然后就转化成一维的LIS问题了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution {
public:
int maxEnvelopes(vector<vector<int>>& envelopes) {
if (envelopes.empty()) return 0;
int size = envelopes.size();
// 按宽 高 从小到大排序
sort(envelopes.begin(), envelopes.end(),
[](vector<int> A, vector<int> B){
if (A[0] == B[0]) return A[1] < B[1];
return A[0] < B[0];
});
// dp[i] 表示以envelopes[i]结尾的最多的信封数
// dp[i] = max{dp[j]} + 1 其中 j < i
// && envelops[j][0] < envelops[i][0]
// && envelops[j][1] < envelops[i][1]
vector<int> dp(size, 0);
int ans = 1;
for (int i = 0; i < size; ++i){
int cur_max = 0;
for (int j = 0; j < i; ++j){
if (envelopes[j][0] < envelopes[i][0] &&
envelopes[j][1] < envelopes[i][1] && cur_max < dp[j])
cur_max = dp[j];
}
dp[i] = cur_max + 1;
ans = max(ans, dp[i]);
}
return ans;
}
};