【LeetCode】354. Russian Doll Envelopes 俄罗斯套娃信封问题(Hard)(JAVA)
题目地址: https://leetcode.com/problems/russian-doll-envelopes/
题目描述:
You have a number of envelopes with widths and heights given as a pair of integers (w, h). One envelope can fit into another if and only if both the width and height of one envelope is greater than the width and height of the other envelope.
What is the maximum number of envelopes can you Russian doll? (put one inside other)
Note:
Rotation is not allowed.
Example:
Input: [[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]).
题目大意
给定一些标记了宽度和高度的信封,宽度和高度以整数对形式 (w, h) 出现。当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。
请计算最多能有多少个信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。
说明:
不允许旋转信封。
解题方法
迭代+记忆
- 采用迭代+记忆的方法,记住 dp[i] 后续你能套几个,不断迭代,计算 dp[next] 的个数
- 采用函数 mH 来计算 index 位置后续能套多少个
class Solution {
public int maxEnvelopes(int[][] envelopes) {
int[] dp = new int[envelopes.length];
int max = 0;
for (int i = 0; i < envelopes.length; i++) {
if (dp[i] <= 0) {
mH(envelopes, dp, i);
}
max = Math.max(max, dp[i]);
}
return max;
}
public int mH(int[][] envelopes, int[] dp, int index) {
if (dp[index] > 0) return dp[index];
int max = 1;
for (int i = 0; i < envelopes.length; i++) {
if (i == index || envelopes[i][0] <= envelopes[index][0] || envelopes[i][1] <= envelopes[index][1]) continue;
max = Math.max(max, mH(envelopes, dp, i) + 1);
}
dp[index] = max;
return max;
}
}
执行耗时:709 ms,击败了5.04% 的Java用户
内存消耗:39.4 MB,击败了76.09% 的Java用户
优化
- 采用排序+最长子序列的方法
- 首先对 envelopes 二维数组进行排序,按照 envelopes[i][0] 小的在前,如果相等,envelopes[i][1] 大的在前
- 如: [2, 3], [2, 4], [3, 2], [3, 4] 排序为: [2, 4], [2, 3], [3, 4], [3, 2], 所以如果 envelopes[i][1] > envelopes[j][1] 的话 ,肯定满足 envelopes[i][0] > envelopes[j][0]
- 所以只要对 envelopes[i][1] 求最长递增序列即可
class Solution {
public int maxEnvelopes(int[][] envelopes) {
Arrays.sort(envelopes, (a, b) -> (a[0] - b[0] == 0 ? b[1] - a[1] : a[0] - b[0]));
int[] dp = new int[envelopes.length];
int len = 0;
for (int i = 0; i < envelopes.length; i++) {
if (len == 0 || dp[len - 1] < envelopes[i][1]) {
dp[len] = envelopes[i][1];
len++;
} else {
int start = 0;
int end = len - 1;
while (start <= end) {
int mid = start + (end - start) / 2;
if (dp[mid] == envelopes[i][1]) {
start = mid;
break;
} else if (dp[mid] > envelopes[i][1]) {
end = mid - 1;
} else {
start = mid + 1;
}
}
dp[start] = envelopes[i][1];
}
}
return len;
}
}
执行耗时:12 ms,击败了89.19% 的Java用户
内存消耗:39.5 MB,击败了67.33% 的Java用户
![](https://i-blog.csdnimg.cn/blog_migrate/6c56d31f951aece27c5faae608dfac2e.jpeg#pic_center)