Lintcode602。マトリョーシカ封筒
タイトルの説明:特定の数の封筒を指定します。整数のペア(w、h)は、それぞれ封筒の幅と高さを表します。一方の封筒の幅と高さがもう一方の封筒よりも大きい場合は、別の封筒を下に置くことができます。エンベロープネスティングレベルの最大数を見つけます。
この質問が最も一般的なアイデア([動的計画法-ソリティア(1次元座標型)] Lintcode 76.最長昇順サブシーケンスと同様)で処理される場合、ループが2層あるため、時間計算量は時間の経過とともに複雑になります。特定の最適化を通じて、元のアルゴリズムの第2レベルのループを削除する必要があります。
ここでは、最初に一般的な方法を示し(時間計算量を超え、ACは不可能)、次に最適化された方法を示します。
//1. 普通方法,时间复杂度会超
class Solution {
public:
/**
* @param envelopes: a number of envelopes with widths and heights
* @return: the maximum number of envelopes
*/
int maxEnvelopes(vector<vector<int>> &envelopes) {
if (0 == envelopes.size()) {
return 0;
}
//1. 按第一维排序
sort(envelopes.begin(), envelopes.end());
//2. 对第二维使用接龙型动态规划
//2.1 初始化
vector<int> f(envelopes.size(), 1);//任何一个位置都可能是起始位置
//2.2 状态转移
for (int i = 1; i < envelopes.size(); ++i) {
for (int j = 0; j < i; ++j) {
if (envelopes[j][1] < envelopes[i][1] &&
envelopes[j][0] < envelopes[i][0]) {
f[i] = max(f[i], f[j] + 1);
}
}
}
//2.3 答案
auto maxPlies = max_element(f.begin(), f.end());
return *maxPlies;
}
};
//2. 进行了优化,可以通过OJ
class Solution {
public:
/**
* @param envelopes: a number of envelopes with widths and heights
* @return: the maximum number of envelopes
*/
int maxEnvelopes(vector<vector<int>> &envelopes) {
if (envelopes.empty()) {
return 0;
}
sort(envelopes.begin(), envelopes.end(), cmp);
int n = envelopes.size();
vector<int> dp;
for (int i = 0; i < n; i++) {
auto it = lower_bound(dp.begin(), dp.end(), envelopes[i][1]);
if (it == dp.end()) {
dp.push_back(envelopes[i][1]);
}
else {
*it = envelopes[i][1];
}
}
return dp.size();
}
static bool cmp(vector<int> &a, vector<int> &b) {
if (a[0] == b[0]) {
return a[1] > b[1];
}
return a[0] < b[0];
}
};