Leetcode 406 根据身高重建队列
问题重述
每个 people[i] = [hi, ki] 表示第 i 个人的身高为 hi ,前面 正好 有 ki 个身高大于或等于 hi 的人。
请你重新构造并返回输入数组 people 所表示的队列。返回的队列应该格式化为数组 queue ,其中 queue[j] = [hj, kj] 是队列中第 j 个人的属性。
示例 1:
输入:people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
输出:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
解释:
编号为 0 的人站在前面因为他前面没有比他身高高或者一样高的人,但是7比5高所以[5,0][7,0].
然后[5,2]因为前面有两个人身高大于等于他的身高。
然后[6,1]因为前面有一个人身高为7大于6
然后[4,4]因为前面四个人身高都高于4
最后[7,1]因为前面只有一个人身高和他一样
解法一:
思路
拓扑排序的思想。只需要每次找到编号为0的人,并且按照身高从小到大依次存到数组。然后将其他比他身高还要矮的编号减一(因为前面一定至少有一个人比他高了,所以可以少考虑已经存到数组里的人)。比如[5,0] [7,0] [4,1] ,[5,0]一定是排在第一个,然后4<5所以4的编号减一变成0,第二次循环时候4<7所以[4,1]先存进数组,最后才是[7,0]进数组。这样一直进行下去就可以得到最后答案。
最终代码
class Solution {
public:
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
vector<vector<int>> ans;
vector<vector<int>> process(people);
int n = people.size();
for (int i = 0; i < n; i++) {
int flag = -1;
for (int j = 0; j < n; j++) {
if (people[j][1] == 0) {
if(flag == -1) flag = j;
else flag = people[flag][0] < people[j][0] ? flag : j;
}
}
ans.push_back(process[flag]);
for(int j = 0; j < n; j++) {
if(people[j][0] <= process[flag][0]) people[j][1]--;
}
}
return ans;
}
};
解法二:
思路
这个解法非常巧妙。根据题目的意思就是,个子高的人看不到个子矮的,因为个子高的编号是根据前面比他高的人的数量编号的。所以我们可以按照个子由大到小降序排序,先排个子高的,再根据编号插入个子矮的人,因为个子矮的影响不到个子高的位置。
所以我们将他们的身高由大到小排序,将hi为第一关键词降序。将ki为第二关键词升序排序,因为[5,0][5,1]两个人,[5,0]一定是排在[5,1]前面的。
插入怎么插入,就是比如
people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]]
第一轮排序过后是:[7,0], [7,1], [6,1], [5,0], [5,2], [4,4]
插入[7,1]的时候直接插到第二个位置
接着插入[6,1]根据编号插到编号为1的前面,所以结果是[7,0][6,1][7,1]
接着插入[5,0]所以插到第零个前面结果是[5,0][7,0][6,1][7,1]
接着插入[5,2]说明前面两个人身高大于等于他,因为是按照身高由大到小排序,所以之前插入的身高一定大于等于他,所以他直接插到位置2的前面就可以,结果是:[5,0][7,0][5,2][6,1][7,1]
因此最后的输出:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]]
最终代码
class Solution {
public:
vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
sort(people.begin(), people.end(), [](const vector<int>& u, const vector<int>& v) {
return u[0] > v[0] || (u[0] == v[0] && u[1] < v[1]);
}); //结合lambda自定义排序,第一关键词为hi,第二关键词为ki
vector<vector<int>> ans;
for (const vector<int>& person: people) {
ans.insert(ans.begin() + person[1], person);
}
return ans;
}
};