題目描述
有個馬戲團正在設計疊羅漢的表演節目,一個人要站在另一人的肩膀上。出於實際和美觀的考慮,在上面的人要比下面的人矮一點且輕一點。已知馬戲團每個人的身高和體重,請編寫代碼計算疊羅漢最多能疊幾個人。
示例:
輸入:height = [65,70,56,75,60,68] weight = [100,150,90,190,95,110]
輸出:6
解釋:從上往下數,疊羅漢最多能疊 6 層:(56,90), (60,95), (65,100), (68,110), (70,150), (75,190)
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/circus-tower-lcci
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
解題思路
- 這裏有一個問題,就是上一層要比下一層矮一點瘦一點,也就是說在身高相同的情況下,只能選一個最瘦的
- 這道題就是求一個最長上升子序列,使得第i個比i-1個的體重小一點,身高矮一點。
- 最長上升子序列有兩種求法,動態規劃和二分法
- 動態規劃的dp[i]指的是以數組中第i個元素結尾的最長上升序列的長度
- 二分法的d[i]是單調遞增數組,d[i]代表的是長度爲i的上升子序列的最後一個元素的值
- 首先應該對身高排序,如果升高一致,對體重進行倒序排序,這裏參考了題解,人家通過構建二維數組,使用庫函數巧妙地解決了這個問題
- 對體重採用倒序排列,是爲了在後續採用貪心+二分法,解決最長子串問題時,在身高相同的情況下,儘可能選擇體重輕的那一個人。
- 總結:這道題鞏固了貪心+二分,促使我看了binarySearch的源碼,爲怎麼實現多條件排序提供了套路
代碼
class Solution {
public int bestSeqAtIndex(int[] height, int[] weight) {
if(height == null || weight == null || height.length == 0 || weight.length == 0 || weight.length != height.length) return 0;
int[][] person = new int[height.length][2];
for(int i = 0; i < height.length; i++){
person[i] = new int[]{height[i], weight[i]};
}
Arrays.sort(person, (o1, o2) -> o1[0] == o2[0] ? o2[1] - o1[1] : o1[0] - o2[0]);
int[] d = new int[height.length];
d[0] = person[0][1];
int len = 1;
for(int i = 1; i < height.length; i++){
int index = Arrays.binarySearch(d, 0, len, person[i][1]);
if(index < 0){
index = -(index + 1);
}
d[index] = person[i][1];
if(index == len) ++len;
}
return len;
}
}