leecode 解题总结:354. Russian Doll Envelopes

俄罗斯套娃信封问题
本文探讨了俄罗斯套娃信封问题,通过宽度排序后利用高度寻找最长递增子序列,以此确定最大套叠数量。这是一道经典的面试题,涉及排序与动态规划算法。
#include <iostream>
#include <stdio.h>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
/*
问题:
You have a number of envelopes with widths and heights given as a pair of integers (w, h). One envelope can fit into another if and only if both the width and height of one envelope is greater than the width and height of the other envelope.

What is the maximum number of envelopes can you Russian doll? (put one inside other)

Example:
Given envelopes = [[5,4],[6,4],[6,7],[2,3]], the maximum number of envelopes you can Russian doll is 3 ([2,3] => [5,4] => [6,7]).

分析:envelope:信封。此题是将信封不断装入另一个较大的信封中。
较小的信封必须宽度和高度都小于较大信封的宽度,高度才可以被放入。
问最多可以放入多少个信封。
这是程序员面试金典的一道题目。是最长递增子序列题目的翻版。
最长递增子序列:dp[i] = max(A[i] < A[j] > dp[j] + 1 : dp[i]),其中j属于i+1~n-1
这里由于存在宽度和高度两个变量,而最长递增子序列只有一维,但位置是固定的。
我们的目的就是通过某一维度(例如宽度)来固定好顺序,然后用另一维度(例如高度),
来进行递增子序列的判断,从而将问题转化为递增子序列问题。

举例:
先将该信封按照宽度排序,得到的序列
[2,3],[5,4],[6,4],[6,7]
然后不看宽度(宽度已经用于排序),只看高度,得到如下序列
3,4,4,7
则最长递增子序列的长度为3,之前的宽度已经符合,无需再管宽度,
只要关注高度即可。
注意由于宽度可能是相同的,宽度如果相同需要过滤

输入:
4(数据的组数)
5 4
6 4
6 7
2 3
1
1 2
2
1 2
2 2

5
4 5
4 6
6 7
2 3
1 1
输出:
3
1
1
4
报错:
Input:
[[4,5],[4,6],[6,7],[2,3],[1,1]]
Output:
5
Expected:
4

关键:
1 这里由于存在宽度和高度两个变量,而最长递增子序列只有一维,但位置是固定的。
我们的目的就是通过某一维度(例如宽度)来固定好顺序,然后用另一维度(例如高度),
来进行递增子序列的判断,从而将问题转化为递增子序列问题。
2 注意由于宽度可能是相同的,宽度如果相同需要过滤
*/

bool compare(const pair<int, int>& pairA , const pair<int, int>& pairB)
{
	return pairA.first < pairB.first;
}

class Solution {
public:
    int maxEnvelopes(vector<pair<int, int>>& envelopes) {
		if(envelopes.empty())
		{
			return 0;
		}
		sort(envelopes.begin() , envelopes.end() , compare);
		int size = envelopes.size();
		//开始计算最长递增子序列
		vector<int> dp(size , 1);
		int maxLen = 1;
		for(int i = size - 2; i >= 0 ; i--)
		{
			for(int j = i + 1 ; j <= size - 1 ; j++)
			{
				//注意由于宽度可能是相同的,宽度如果相同需要过滤
				if(envelopes.at(i).second < envelopes.at(j).second && envelopes.at(i).first < envelopes.at(j).first)
				{
					dp.at(i) = max(dp.at(i) , dp.at(j) + 1);
				}
			}
			maxLen = max(maxLen  ,dp.at(i));
		}
		return maxLen;
    }
};

void process()
{
	 vector<pair<int,int> > nums;
	 int num;
	 Solution solution;
	 int result;
	 while(cin >> num )
	 {
		 //压入元素
		 nums.clear();
		 for(int i = 0 ; i < num ; i++)
		 {
			 pair<int,int> envelope;
			 cin >> envelope.first >> envelope.second;
			 nums.push_back(envelope);
		 }
		 result = solution.maxEnvelopes(nums);
		 cout << result << endl;
	 }
}

int main(int argc , char* argv[])
{
	process();
	getchar();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值