ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2020-04-08 17:36:14  阅读:268  来源: 互联网

标签:面试题 return int 金典 height second vector 子序 dp


文章目录

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/二分查找)

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

264 ms 46.5 MB

标签:面试题,return,int,金典,height,second,vector,子序,dp
来源: https://blog.csdn.net/qq_21201267/article/details/105360463

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有