给你一个二维整数数组 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();     } };
  |