腾讯 wxg 测开一面

腾讯 WXG 一面|354. 俄罗斯套娃信封问题

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

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

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

注意:不允许旋转信封。

示例 1:

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

示例 2:

1
2
输入:envelopes = [[1,1],[1,1],[1,1]]
输出:1

提示:

  • 1 <= envelopes.length <= 10^5
  • envelopes[i].length == 2
  • 1 <= wi, hi <= 10^5

0️⃣ 前置题目

300. 最长递增子序列 |DP / 二分

1️⃣ LIS · 动态规划(超时 TLE)

时间复杂度 $O(n^2)$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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);
}
};

2️⃣ 贪心 + 二分查找

时间复杂度:$O(n·logn)$

先排序,再按照 LIS 二分贪心模板求最长递增子序列。因为二者都必须是递增的,所以第二维度需要逆序排序,使得第一维度相同的多个数,最后一个插入的一定是最小值,这样能嵌套的信封最多。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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();
}
};

✍️ Yikun Wu 已发表了 69 篇文章 · 总计 293k 字,采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处

🌀 本站总访问量