文章目錄
1. 題目
有個馬戲團正在設計疊羅漢的表演節目,一個人要站在另一人的肩膀上。出于實際和美觀的考慮,在上面的人要比下面的人矮一點且輕一點。
已知馬戲團每個人的身高和體重,請編寫代碼計算疊羅漢最多能疊幾個人。
示例:
輸入: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)提示:
height
.length
== weight
.length
<= 10000
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/circus-tower-lcci
著作權歸領扣網絡所有。商業轉載請聯系官方授權,非商業轉載請注明出處。
2. 解題
類似題目:
LeetCode 354. 俄羅斯套娃信封問題(最長上升子序 DP/二分查找)
程序員面試金典 - 面試題 08.13. 堆箱子(DP)
2.1 超時解
- 類似于最大上升子序
- 采用DP解法,時間復雜度 O(n2)O(n^2)O(n2),看上面數據規模,超時妥妥的 ( 23 / 43 個通過測試用例 )
class Solution {
public:int bestSeqAtIndex(vector
<int>& height
, vector
<int>& weight
) {int i
, j
, n
= height
.size(),maxP
= 1;vector
<vector
<int>> p(n
);for(i
= 0; i
< n
; ++i
)p
[i
] = {height
[i
], weight
[i
]};sort(p
.begin(),p
.end());vector
<int> dp(n
,1);for(i
= 1; i
< n
; ++i
){for(j
= i
-1; j
>= 0; --j
){if(p
[i
][1] > p
[j
][1]){dp
[i
] = max(dp
[i
], 1+dp
[j
]);maxP
= max(maxP
, dp
[i
]);}}}sort(p
.begin(),p
.end(),[&](auto a
, auto b
){return a
[1] < b
[1];});vector
<int> dp1(n
,1);for(i
= 1; i
< n
; ++i
){for(j
= i
-1; j
>= 0; --j
){if(p
[i
][0] > p
[j
][0]){dp1
[i
] = max(dp1
[i
], 1+dp1
[j
]);maxP
= max(maxP
, dp1
[i
]);}}}return maxP
;}
};
2.2 二分查找
- 思路:對一個變量排序,第一個變量相等的時候,第二個變量降序排列(一會求第二個變量的最長上升子序,避免第一個變量相等也取進去)
- 然后dp[i] 表示長度為 i 的上升子序的 序列最后一個數的最小值(采用二分查找,找到第一個大于等于 target 的)
class Solution {
public:int bestSeqAtIndex(vector
<int>& height
, vector
<int>& weight
) {int i
, idx
=0, n
= height
.size();vector
<pair
<int,int>> p(n
);for(i
= 0; i
< n
; ++i
)p
[i
] = {height
[i
], weight
[i
]};sort(p
.begin(),p
.end(),[](auto a
, auto b
){if(a
.first
==b
.first
)return a
.second
> b
.second
;return a
.first
< b
.first
;});vector
<int> dp(n
);for(i
= 0; i
< n
; ++i
){auto it
= lower_bound(dp
.begin(),dp
.begin()+idx
,p
[i
].second
);*it
= p
[i
].second
;if(it
-dp
.begin()==idx
)idx
++;}return idx
;}
};
404 ms 46.3 MB
class Solution {
public:int bestSeqAtIndex(vector
<int>& height
, vector
<int>& weight
) {int i
, j
, len
=1, n
= height
.size();vector
<pair
<int,int>> p(n
);for(i
= 0; i
< n
; ++i
)p
[i
] = {height
[i
], weight
[i
]};sort(p
.begin(),p
.end(),[](auto a
, auto b
){if(a
.first
==b
.first
)return a
.second
> b
.second
;return a
.first
< b
.first
;});vector
<int> dp(n
);dp
[0] = p
[0].second
;for(i
= 1; i
< n
; ++i
){j
= bs(dp
,0,len
-1,len
,p
[i
].second
);dp
[j
] = p
[i
].second
;if(j
== len
)len
++;}return len
;}int bs(vector
<int>& dp
, int l
, int r
, int len
, int target
){ int mid
;while(l
<= r
){mid
= l
+((r
-l
)>>1);if(dp
[mid
] >= target
){if(mid
==0 || dp
[mid
-1] < target
)return mid
;elser
= mid
-1;}elsel
= mid
+1;}return len
;}
};
264 ms 46.5 MB
總結
以上是生活随笔為你收集整理的程序员面试金典 - 面试题 17.08. 马戏团人塔(最长上升子序 DP/二分查找)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。