Core's ink

Back

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

腾讯 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]]
输出:1
cpp

提示:

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

0️⃣ 前置题目#

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

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

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

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);
    }
};
cpp

2️⃣ 贪心 + 二分查找#

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

先排序,再按照 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
腾讯 wxg 一面|354. 俄罗斯套娃信封问题
https://coooredump.github.io/blog/leetcode/tecent-wxg-russian-doll-envelope/
Author Coredump
Published at April 28, 2025
Comment seems to stuck. Try to refresh?✨