腾讯 WXG 一面|354. 俄罗斯套娃信封问题 ↗#
给你一个二维整数数组 envelopes ,其中 envelopes[i] = [wi, hi] ,表示第 i 个信封的宽度和高度。
当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。
请计算 最多能有多少个 信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。
注意:不允许旋转信封。
示例 1:
输入:envelopes = [[5,4],[6,4],[6,7],[2,3]]
输出:3
解释:最多信封的个数为 3, 组合为: [2,3] => [5,4] => [6,7]。cpp示例 2:
输入:envelopes = [[1,1],[1,1],[1,1]]
输出:1cpp提示:
1 <= envelopes.length <= 10^5envelopes[i].length == 21 <= wi, hi <= 10^5
0️⃣ 前置题目#
✅ 300. 最长递增子序列 ↗|DP / 二分
1️⃣ LIS · 动态规划(超时 TLE)#
时间复杂度
class Solution {
public:
int maxEnvelopes(vector<vector<int>>& envelopes) {
int n = envelopes.size();
vector<pair<int, int>> arr(n);
for (int i = 0; i < n; i++)
arr[i] = {envelopes[i][0], envelopes[i][1]};
ranges::sort(arr);
vector<int> f(n, 1);
for (int i = 0; i < n; i++) {
for (int j = 0; j < i; j++) {
if (arr[i].first > arr[j].first && arr[i].second > arr[j].second) {
f[i] = max(f[i], f[j] + 1);
}
}
}
return ranges::max(f);
}
};cpp2️⃣ 贪心 + 二分查找#
时间复杂度:
先排序,再按照 LIS 二分贪心模板求最长递增子序列。因为二者都必须是递增的,所以第二维度需要逆序排序,使得第一维度相同的多个数,最后一个插入的一定是最小值,这样能嵌套的信封最多。
class Solution {
public:
int maxEnvelopes(vector<vector<int>>& envelopes) {
sort(envelopes.begin(), envelopes.end(), [](auto& a, auto& b) {
return a[0] < b[0] || (a[0] == b[0] && a[1] > b[1]);
});
vector<int> g;
for (auto& e : envelopes) {
auto it = lower_bound(g.begin(), g.end(), e[1]);
if (it == g.end()) {
g.push_back(e[1]);
} else {
*it = e[1];
}
}
return g.size();
}
};cpp