700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 程序员面试金典 - 面试题 17.08. 马戏团人塔(最长上升子序 DP/二分查找)

程序员面试金典 - 面试题 17.08. 马戏团人塔(最长上升子序 DP/二分查找)

时间:2021-08-22 07:54:57

相关推荐

程序员面试金典 - 面试题 17.08. 马戏团人塔(最长上升子序 DP/二分查找)

文章目录

1. 题目2. 解题2.1 超时解2.2 二分查找

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-/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;}else// if(dp[mid] < target)l = mid+1;}return len;//没有找打,说明它是最大的}};

264 ms 46.5 MB

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。