[LeetCode] 354. Russian Doll Envelopes

You are given a 2D array of integers envelopes where envelopes[i] = [wi, hi] represents the width and the height of an envelope.

One envelope can fit into another if and only if both the width and height of one envelope are greater than the other envelope's width and height.

Return the maximum number of envelopes you can Russian doll (i.e., put one inside the other).

Note: You cannot rotate an envelope.

Example 1:

Input: envelopes = [[5,4],[6,4],[6,7],[2,3]]
Output: 3
Explanation: The maximum number of envelopes you can Russian doll is 3 ([2,3] => [5,4] => [6,7]).

Example 2:

Input: envelopes = [[1,1],[1,1],[1,1]]
Output: 1

Constraints:

  • 1 <= envelopes.length <= 105
  • envelopes[i].length == 2
  • 1 <= wi, hi <= 105

俄罗斯套娃信封问题。

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

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

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

注意:不允许旋转信封。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/russian-doll-envelopes
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

这道题类似300题,我直接给出最优解,DP + 二分法。300题是在一个一维数组里找最长的上升子序列。这道题是在一个二维数组<width, height>里寻找一个最长上升子序列,首先需要对 input 数组排序,先对宽度 w 进行升序排序,如果遇到 w 相同的情况,则按照高度 h 降序排序。之后在 h 那个维度上计算 LIS 的长度就是答案。我这里直接粘贴一个大神的截图作参考

 

 然后在 h 上寻找最长递增子序列

 

宽度需要升序排列很好理解,因为只有排在后面的信封宽度更大,才能放得下当前宽度小的信封,这样我们在找的时候就无需担心宽度这个维度的限制了;宽度相同的情况下为什么高度是降序排列是因为题目条件规定宽度或高度相同的两个信封是无法嵌套的,这也就意味着当我们对宽度进行升序排序之后,每个不同宽度的信封我们只能选择一个。此时如果高度还是按升序排列的话,会出现类似下面这个情况。如果我们按 LIS 的常规做法去找,会返回 4,这是不对的。但是如果我们对高度进行降序排列,就可以确保每个宽度的信封只选择一个,就可以规避这个问题。

[(w,h)]=[(1,1),(1,2),(1,3),(1,4)]

时间O(nlogn)

空间O(n)

Java实现

 1 class Solution {
 2     public int maxEnvelopes(int[][] envelopes) {
 3         // corner case
 4         if (envelopes.length < 2) {
 5             return envelopes.length;
 6         }
 7 
 8         // normal case
 9         // <w, h>
10         Arrays.sort(envelopes, (a, b) -> a[0] == b[0] ? b[1] - a[1] : a[0] - b[0]);
11         int[] dp = new int[envelopes.length];
12         int size = 0;
13         for (int[] e : envelopes) {
14             int left = 0;
15             int right = size;
16             while (left < right) {
17                 int mid = left + (right - left) / 2;
18                 if (dp[mid] < e[1]) {
19                     left = mid + 1;
20                 } else {
21                     right = mid;
22                 }
23             }
24 
25             dp[left] = e[1];
26             if (left == size) {
27                 size++;
28             }
29         }
30         return size;
31     }
32 }

 

LIS类相关题目

LeetCode 题目总结

posted @ 2021-03-05 12:57  CNoodle  阅读(578)  评论(0编辑  收藏  举报