题目描述
有个马戏团正在设计叠罗汉的表演节目,一个人要站在另一人的肩膀上。出于实际和美观的考虑,在上面的人要比下面的人矮一点且轻一点。已知马戏团每个人的身高和体重,请编写代码计算叠罗汉最多能叠几个人。
示例:
输入:height = [65,70,56,75,60,68] weight = [100,150,90,190,95,110]
输出:6
解释:从上往下数,叠罗汉最多能叠 6 层:(56,90), (60,95), (65,100), (68,110), (70,150), (75,190)
提示:
-
height.length == weight.length <= 10000
思路
与最长递增子序列问题相似----动态规划算法
代码
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
class Solution {//DP O(N*N);O(N)
public:
int bestSeqAtIndex(vector<int>& height, vector<int>& weight) {
int n = height.size();
vector<vector<int>> lst(n, vector<int>(2));
for (int i = 0; i < n; i++) {
lst[i][0] = height[i];
lst[i][1] = weight[i];
}
sort(lst.begin(), lst.end(), [](const vector<int>& a, const vector<int>& b) {
if (a[0] == b[0]) {
return b[1] < a[1];//体重降序
}
return a[0] < b[0];//升高升序
});
vector<int> w_lst(n);
for (int i = 0; i < n; i++) {
w_lst[i] = lst[i][1];
}
vector<int> dp(n, 1);
for (int i = 1; i < n; i++) {
for (int j = 0; j < i; j++) {
if (w_lst[i] > w_lst[j]) {
dp[i] = max(dp[i], dp[j] + 1);
}
}
}
int maxLen = 0;
for (int i = 0; i < n; i++) {
maxLen = max(maxLen, dp[i]);
}
return maxLen;
}
};
class Solution1 {//贪心+二分 O(NlogN);O(N)
public:
void binarySearch(vector<int>& ans, int num) {
int left = 0, right = ans.size();
while (left < right) {
int mid = (left + right) >> 1;
if (ans[mid] >= num) {
right = mid;
}
else {
left = mid + 1;
}
}
ans[left] = num;
}
int bestSeqAtIndex(vector<int>& height, vector<int>& weight) {
int n = height.size();
vector<vector<int>> lst(n, vector<int>(2));
for (int i = 0; i < n; i++) {
lst[i][0] = height[i];
lst[i][1] = weight[i];
}
sort(lst.begin(), lst.end(), [](const vector<int>& a, const vector<int>& b) {
return a[0] == b[0] ? b[1] < a[1] : a[0] < b[0];
});
vector<int> ans;
ans.push_back(lst[0][1]);
for (int i = 1; i < n; i++) {
int h = lst[i][0], w = lst[i][1];
if (w > ans.back()) {
ans.push_back(w);
}
else {
binarySearch(ans, w);//贪心想法:让上面的人更轻(找到一个更轻的人就换位置)
}
}
return ans.size();
}
};
class Solution_test {//测试排序函数用
public:
vector<vector<int>> print(vector<int>& height, vector<int>& weight) {
int n = height.size();
vector<vector<int>> lst(n, vector<int>(2));
for (int i = 0; i < n; i++) {
lst[i][0] = height[i];
lst[i][1] = weight[i];
}
sort(lst.begin(), lst.end(), [](const vector<int>& a, const vector<int>& b) {
if (a[0] == b[0]) {
return b[1] < a[1];
}
return a[0] < b[0];
});
return lst;
}
};
vector<int> split(string params_str) {
vector<int> p;
while (params_str.find(",") != string::npos) {
int found = params_str.find(",");
p.push_back(stoi(params_str.substr(0, found)));
params_str = params_str.substr(found + 1);
}
p.push_back(stoi(params_str));
return p;
}
vector<vector<int>> v;
vector<int> p;
vector<vector<int>> split_2_dimention(string s) {
s += " ";//防止最后一个]后面没有元素所导致的越界
while (s.find("]") != string::npos) {
int found_right = s.find("]");
string s1 = s.substr(1, found_right - 1);
p = split(s1);
v.push_back(p);
s = s.substr(found_right + 2);//取第二个vector,这里可能会越界
p.clear();
}
return v;
}
int main() {
//string input_str1;
//getline(cin, input_str1);//nums1 = [1,2,3,2,1]
//input_str1 = input_str1.substr(1, input_str1.size() - 2);
//vector<int> arr1 = split(input_str1);
//string input_str2;
//getline(cin, input_str2);//nums2 = [3,2,1,4,7]
//input_str2 = input_str2.substr(1, input_str2.size() - 2);
//vector<int> arr2 = split(input_str2);
string input_str;
getline(cin,input_str);//height = [65,70,56,75,60,68],weight = [100,150,90,190,95,110]
vector<vector<int>> arr_2dimen;
arr_2dimen = split_2_dimention(input_str);
Solution_test a;
vector<vector<int>> result = a.print(arr_2dimen[0], arr_2dimen[1]);
for (int i = 0; i < result.size(); i++) {
for (int j = 0; j < result[i].size(); j++) {
cout << result[i][j] << " ";
}
cout << endl;
}
Solution b;
cout << b.bestSeqAtIndex(arr_2dimen[0], arr_2dimen[1]) << endl;
Solution1 c;
cout << c.bestSeqAtIndex(arr_2dimen[0], arr_2dimen[1]) <<endl;
}