Leetcode 406 根据身高重建队列

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;
    }
};

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

UPC YR

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值