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]).
我的思路:和最长递增子序列是一个思路。先把信封按照一条边从小到大排序。然后按照最长递增子序列的递归思路做。注意要同时比较长和宽。
class Solution {
public:
int maxEnvelopes(vector<pair<int, int>>& envelopes) {
sort(envelopes.begin(),envelopes.end());
int n=envelopes.size();
if(n<=1) return n;
vector<int> dp(n,1);
int res=0;
for(int i=1;i<n;i++)
{
for(int j=i-1;j>=0;j--)
{
if(envelopes[i].first>envelopes[j].first&&envelopes[i].second>envelopes[j].second)
dp[i]=max(dp[i],dp[j]+1);
}
res=max(res,dp[i]);
}
return res;
}
};
上题是n方解法的,通过二分查找形式的动态规划可以实现nlogn。但是这种方法的实现实现复杂度降低的原理是在已有长度的信封嵌套中保存一个最后信封最小的那个。
比如【2,2】【3,4】【3,3】【4,4】,长度为2的最小信封结尾应该是【3,3】而不是【3,4】,最长序列应该是3,但是如果只更新到【4,4】不能容纳【3,4】,结果不正确。
另一个例子:
【2,3】【3,4】【3,3】【4,4】 ,【3,4】可以容纳【2,3】,但是【3,3】不能容纳【2,3】,结果是最长为2.
解决的办法是:
自定义排序规则。使得长小的排在前边。长大的排在后边,如果长相同,宽大的排在前面宽小的排在后边。二分查找的时候只比较信封的宽度。。,dp数组只保存宽度。
比如已经排好序的【2,2】【3,4】【3,3】【4,4】,当遍历到【3,3】时,【3,3】应该排在【3,4】的前边,因为第二个数小,所以返回【3,4】的位置,替换【3,4】
比如:【2,3】【3,4】【3,3】【4,4】 ,遍历到【3,3】时,找到的位置是【2,3】,这个时候改变成【3,3】【3,4】,虽然【3,3】扩大了,但是后面的数如果可能构成更长的序列,长肯定要比3大才行,所以不影响最后的长度。长度为3的子序列是跟【3,4】比较的。
使用神奇的lambda表达式:
注意,当lambda表达式的函数体除了return语句之外还有其他语句,必须制定返回类型。
class Solution {
public:
int maxEnvelopes(vector<pair<int, int>>& envelopes) {
sort(envelopes.begin(),envelopes.end(),
[](const pair<int,int>& a,const pair<int,int>& b)->bool{if(a.first==b.first) return a.second>b.second;
else
return a.first<b.first;});//使用lambda表达式
vector<int> dp;
for(int i=0;i<envelopes.size();i++)
{
auto it=std::lower_bound(dp.begin(),dp.end(),envelopes[i].second);
if(it!=dp.end())
*it=envelopes[i].second;
else
dp.push_back(envelopes[i].second);
}
return dp.size();
}
};
使用函数对象:注意函数对象后面需要加括号
class Solution {
public:
int maxEnvelopes(vector<pair<int, int>>& envelopes) {
sort(envelopes.begin(),envelopes.end(),comp());
vector<int> dp;
for(int i=0;i<envelopes.size();i++)
{
auto it=std::lower_bound(dp.begin(),dp.end(),envelopes[i].second);
if(it!=dp.end())
*it=envelopes[i].second;
else
dp.push_back(envelopes[i].second);
}
return dp.size();
}
struct comp{
bool operator()(const pair<int,int>& a,const pair<int,int>& b)
{
if(a.first==b.first) return a.second>b.second;
else
return a.first<b.first;
}
};
};