本文地址:http://blog.csdn.net/qq_26437925/article/details/52228515
leetcode 354. Russian Doll Envelopes题目地址:
https://leetcode.com/problems/russian-doll-envelopes/
AC代码
class Solution {
public:
int maxEnvelopes(vector<pair<int, int>>& envelopes) {
int n = envelopes.size();
if (n <= 1)
return n;
// sort by p1.first < p2.first, if equal, then p1.second > p2.second
sort(envelopes.begin(), envelopes.end(),
[](pair<int, int> p1, pair<int, int> p2){
if (p1.first < p2.first)
return true;
if (p1.first == p2.first)
return p1.second > p2.second;
return false;
}
);
vector<int> h(n);
int hlen = 0; // number of elements in array h
h[0] = envelopes[0].second;
for (int i = 1; i < n; i++)
{
int right = hlen;
int left = 0;
while (left <= right) { // binary search
int mid = (left + right) / 2;
if (h[mid] < envelopes[i].second) {
left = mid + 1;
}
else {
right = mid - 1;
}
}
hlen = max(hlen, left); // hlen max(hlen, left)
h[left] = envelopes[i].second;
}
return hlen + 1;
}
};
时间复杂度 O(nlogn) (n为所求二元组的长度)
其中:排序nlog(n), 求最长递增子序列也是O(nlogn)
空间复杂度O(n), 即构造的h数组
解题思路
对比一元最长递增子序列求解方法(时间复杂度:O(nlog(n)))
h[i] 的意义:仍然是遍历到某个数时,长度为i+1的最小末尾
例如 数组 2 1 6 4 5 2 7 4
hi
最终的h 1 3 4 7
即长度为 0+1 = 1 时 ,最小某尾数字是 1
长度为 1+1 = 2 时 ,最小某尾数字是 3
长度为 2+1 = 3 时 ,最小某尾数字是 4
长度为 3+1 = 4 时 ,最小某尾数字是 7
总之,在遍历到某个数时,长度为所有的的 最小末尾 都知道,这样最长的也就知道,可以参考牛客网左程云的算法视频讲解和图书
只是在二元组中,需要先对first从小到大排序,在对second从大到小排序,然后对second 按照一元最长递增子序列的求解方法求解即可。
例如 envelopes = [[6,7],[4,5],[4,3],[5,4],[1,2]]
按照上述排序方法,排序后如下
first | 1 | 4 | 4 | 5 | 6 |
---|---|---|---|---|---|
second | 2 | 5 | 3 | 4 | 7 |
这样比较seconde值时,后面的小数可以替换前面的大数
即最后能够得到 [1,2] => [4,3] => [5,4] => [6,7]
倘若排序时 first second 都按从小到大
first | 1 | 4 | 4 | 5 | 6 |
---|---|---|---|---|---|
second | 2 | 3 | 5 | 4 | 7 |
则得到 [1,2] => [4,5] => [6,7]
参考:
https://discuss.leetcode.com/topic/47469/java-nlogn-solution-with-explanation
马戏团
搜狐员工小王最近利用假期在外地旅游,在某个小镇碰到一个马戏团表演,精彩的表演结束后发现团长正和大伙在帐篷前激烈讨论,小王打听了下了解到, 马戏团正打算出一个新节目“最高罗汉塔”,即马戏团员叠罗汉表演。考虑到安全因素,要求叠罗汉过程中,站在某个人肩上的人应该既比自己矮又比自己瘦,或相等。 团长想要本次节目中的罗汉塔叠的最高,由于人数众多,正在头疼如何安排人员的问题。小王觉得这个问题很简单,于是统计了参与最高罗汉塔表演的所有团员的身高体重,并且很快找到叠最高罗汉塔的人员序列。 现在你手上也拿到了这样一份身高体重表,请找出可以叠出的最高罗汉塔的高度,这份表中马戏团员依次编号为1到N。
输入描述:
首先一个正整数N,表示人员个数。
之后N行,每行三个数,分别对应马戏团员编号,体重和身高。
输出描述:
正整数m,表示罗汉塔的高度。
输入例子:
6
1 65 100
2 75 80
3 80 100
4 60 95
5 82 101
6 81 70
输出例子:
4
最终的意思是:
a1 > a2 && b1 >= b2 或者 a1 == a2 && b1 == b2
那么 [a2,b2] => [a1,b1]
这题采用动归求解
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
typedef struct node
{
int no;
int w;
int h;
}Per;
int main()
{
//freopen("in.txt", "r", stdin);
int n;
while (scanf("%d", &n) != EOF)
{
vector<Per> vp;
Per tmp;
for (int i = 0; i < n; i++)
{
scanf("%d%d%d", &tmp.no, &tmp.w, &tmp.h);
vp.push_back(tmp);
}
sort(vp.begin(), vp.end(),
[](Per p1, Per p2){
if (p1.w < p2.w) //体重一定要小
return true;
if (p1.w == p2.w) // 体重相等时,身高一定要小
return p1.h < p2.h;
return false;
}
);
vector<int> dp(n,1);
int maxL = 1;
for (int i = 1; i < n; i++)
{
for (int j = 0; j < i; j++)
{
if (vp[i].w == vp[j].w && vp[i].h == vp[j].h)
dp[i] = max(dp[i], dp[j] + 1);
if (vp[i].w > vp[j].w && vp[i].h >= vp[j].h)
dp[i] = max(dp[i], dp[j] + 1);
}
maxL = max(maxL, dp[i]);
}
printf("%d\n", maxL);
}// end while
return 0;
}
与二元组最长递增子序列很类似,不过条件不一样,无法套用