马戏团人塔
难度:
标签:
题目描述
A circus is designing a tower routine consisting of people standing atop one another's shoulders. For practical and aesthetic reasons, each person must be both shorter and lighter than the person below him or her. Given the heights and weights of each person in the circus, write a method to compute the largest possible number of people in such a tower.
Example:
Input: height = [65,70,56,75,60,68] weight = [100,150,90,190,95,110] Output: 6 Explanation: The longest tower is length 6 and includes from top to bottom: (56,90), (60,95), (65,100), (68,110), (70,150), (75,190)
Note:
height.length == weight.length <= 10000
代码结果
运行时间: 146 ms, 内存: 18.4 MB
// 题目思路:
// 同样的,我们需要根据身高和体重来构建一个最长递增子序列。
// 使用Java Stream来对数据进行排序,并利用二分查找来寻找LIS。
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class CircusTowerStream {
public int maxEnvelopes(int[] height, int[] weight) {
List<int[]> people = Arrays.stream(height)
.boxed()
.map(i -> new int[]{height[i], weight[i]})
.sorted((a, b) -> a[0] == b[0] ? b[1] - a[1] : a[0] - b[0])
.collect(Collectors.toList());
int[] dp = new int[people.size()];
int maxLength = 0;
for (int[] person : people) {
int weightValue = person[1];
int left = 0, right = maxLength;
while (left < right) {
int mid = (left + right) / 2;
if (dp[mid] < weightValue) left = mid + 1;
else right = mid;
}
dp[left] = weightValue;
if (left == maxLength) maxLength++;
}
return maxLength;
}
public static void main(String[] args) {
CircusTowerStream tower = new CircusTowerStream();
int[] height = {65, 70, 56, 75, 60, 68};
int[] weight = {100, 150, 90, 190, 95, 110};
System.out.println(tower.maxEnvelopes(height, weight));
}
}
解释
方法:
首先,对输入的身高和体重进行处理,按身高升序、体重降序的方式进行排序,这样可以确保在相同身高的情况下,体重较重的人排在前面。然后,使用一个动态数组 d_tail 来记录当前可以叠罗汉的最长序列,初始时只包含第一个人的体重。接着,遍历排序后的每个人,对于每个人,检查他们的体重是否可以放在当前的叠罗汉序列的末尾,如果可以,则将他们的体重添加到序列末尾;否则,使用二分查找在序列中找到一个位置,使得该位置之前的所有人的体重都小于当前人的体重,并将当前人的体重放在这个位置。最后,返回 d_tail 的长度,即为最多能叠的人数。
时间复杂度:
O(n log n)
空间复杂度:
O(n)
代码细节讲解
🦆
为什么在排序时要先按身高升序排列,接着对于相同身高的人按体重降序排列?
▷🦆
在使用动态数组 d_tail 记录最长序列时,这个数组的每个元素代表的是什么含义?
▷🦆
为什么当新加入的人的体重大于 d_tail 数组的最后一个元素时,选择将该体重直接添加到 d_tail 的末尾?
▷