生活随笔
收集整理的這篇文章主要介紹了
程序员面试金典 - 面试题 17.08. 马戏团人塔(最长上升子序 DP/二分查找)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
文章目錄
1. 題目
有個(gè)馬戲團(tuán)正在設(shè)計(jì)疊羅漢的表演節(jié)目,一個(gè)人要站在另一人的肩膀上。出于實(shí)際和美觀的考慮,在上面的人要比下面的人矮一點(diǎn)且輕一點(diǎn)。
已知馬戲團(tuán)每個(gè)人的身高和體重,請編寫代碼計(jì)算疊羅漢最多能疊幾個(gè)人。
示例:
輸入:height
= [65,70,56,75,60,68] weight
= [100,150,90,190,95,110]
輸出:
6
解釋:從上往下數(shù),疊羅漢最多能疊
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
著作權(quán)歸領(lǐng)扣網(wǎng)絡(luò)所有。商業(yè)轉(zhuǎn)載請聯(lián)系官方授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。
2. 解題
類似題目:
LeetCode 354. 俄羅斯套娃信封問題(最長上升子序 DP/二分查找)
程序員面試金典 - 面試題 08.13. 堆箱子(DP)
2.1 超時(shí)解
- 類似于最大上升子序
- 采用DP解法,時(shí)間復(fù)雜度 O(n2)O(n^2)O(n2),看上面數(shù)據(jù)規(guī)模,超時(shí)妥妥的 ( 23 / 43 個(gè)通過測試用例 )
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 二分查找
- 思路:對一個(gè)變量排序,第一個(gè)變量相等的時(shí)候,第二個(gè)變量降序排列(一會求第二個(gè)變量的最長上升子序,避免第一個(gè)變量相等也取進(jìn)去)
- 然后dp[i] 表示長度為 i 的上升子序的 序列最后一個(gè)數(shù)的最小值(采用二分查找,找到第一個(gè)大于等于 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
總結(jié)
以上是生活随笔為你收集整理的程序员面试金典 - 面试题 17.08. 马戏团人塔(最长上升子序 DP/二分查找)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。