LeetCode原题:
给你一个二维整数数组 envelopes ,其中 envelopes[i] = [wi, hi] ,表示第 i 个信封的宽度和高度。
当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。
请计算 最多能有多少个 信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。
注意:不允许旋转信封。
示例 1:
输入:envelopes = [[5,4],[6,4],[6,7],[2,3]]
输出:3
解释:最多信封的个数为 3, 组合为: [2,3] => [5,4] => [6,7]。
示例 2:
输入:envelopes = [[1,1],[1,1],[1,1]]
输出:1
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/russian-doll-envelopes
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目解析:
该题实质是将二维的最长递增子序列问题转换为一维的最长递增子序列问题(参考文献 《labuladong的算法小抄》 作者:付东来)
C++代码
#include <iostream>
#include <vector>
#include <algorithm>
using std::vector;
int maxEnvelopes(vector<vector<int>>& envelopes);
bool comp(const vector<int>& a, const vector<int>& b);
int main()
{
vector<vector<int>> envelopes;
int arr[][2] = { {5, 4}, {6, 4}, {6, 7}, {2, 3} };
for (int *i : arr)
{
vector<int> a;
a.push_back(i[0]);
a.push_back(i[1]);
envelopes.push_back(a);
}
std::cout << maxEnvelopes(envelopes) << std::endl;
system("pause");
return 0;
}
int maxEnvelopes(vector<vector<int>>& envelopes) //将二维最长递增子序列转换成一维最长递增子序列
{
sort(envelopes.begin(), envelopes.end(), comp);
//LIS算法(最长递增子序列)
vector<int> dp(envelopes.size(), 1); //dp记录以envelops[i][1]结尾的最长递增子序列的长度
for (int i = 0; i < envelopes.size(); ++i)
{
for (int j = 0; j < i; ++j)
{
if (envelopes[i][1] > envelopes[j][1]) //找到前面结尾比envelops[i][1]小的子序列
dp[i] = dp[i] > dp[j] + 1 ? dp[i] : dp[j] + 1; //更新以envelops[i][1]结尾的最长递增子序列的长度
}
}
int res = 0;
for (int i = 0; i < dp.size(); ++i) //查找最长子序列
res = res > dp[i] ? res : dp[i];
return res;
}
bool comp(const vector<int>& a, const vector<int>& b) //回调函数
{
if (a[0] < b[0]) //先对宽度进行升序
return true;
else if (a[0] > b[0])
return false;
else //如果宽度相等,则按照高度h降序排序
{
if (a[1] > b[1])
return true;
else
return false;
}
}
LeetCode网页代码
class Solution {
public:
int maxEnvelopes(vector<vector<int>>& envelopes) //将二维最长递增子序列转换成一维最长递增子序列
{
sort(envelopes.begin(), envelopes.end(), comp);
//LIS算法(最长递增子序列)
vector<int> dp(envelopes.size(), 1); //dp记录以envelops[i][1]结尾的最长递增子序列的长度
for (int i = 0; i < envelopes.size(); ++i)
{
for (int j = 0; j < i; ++j)
{
if (envelopes[i][1] > envelopes[j][1]) //找到前面结尾比envelops[i][1]小的子序列
dp[i] = dp[i] > dp[j] + 1 ? dp[i] : dp[j] + 1; //更新以envelops[i][1]结尾的最长递增子序列的长度
}
}
int res = 0;
for (int i = 0; i < dp.size(); ++i) //查找最长子序列
res = res > dp[i] ? res : dp[i];
return res;
}
static bool comp(const vector<int>& a, const vector<int>& b) //设置为静态成员函数
{
if (a[0] < b[0]) //先对宽度进行升序
return true;
else if (a[0] > b[0])
return false;
else //如果宽度相等,则按照高度h降序排序
{
if (a[1] > b[1])
return true;
else
return false;
}
}
};
注意点:
当使用<algorithm>头文件中的sort函数对vector容器进行排序时,由于普通成员函数的参数列表中有一个隐含的参数this,将导致sort函数内部调用回调函数comp()时产生形参与实参不匹配的情况,如果设置为静态成员函数,由于静态成员函数不含this指针,则不会产生形参与实参不匹配的情况。
参考文献:reference to non-static member function must be called_奋斗的程序猿的博客-CSDN博客
注:该题的C++解法根据《labuladong的算法小抄》第二章——信封嵌套问题中的JAVA解法改编而来,仅用于学习交流。