1. 题目

假设有打乱顺序的一群人站成一个队列。 每个人由一个整数对(h, k)表示,其中h是这个人的身高,k是排在这个人前面且身高大于或等于h的人数。 编写一个算法来重建这个队列。

注意: 总人数少于1100人

示例 输入: [[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]

输出: [[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/queue-reconstruction-by-height 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2. 解题思路

2.1. 递归回溯

image-20201116152912899

一开始是按先k升序,再h升序排序,先排[5,0],再排[7,0],排第三个人的时候有3种选择,只能想到递归回溯了。然后就超时了。。

所以应该有其他算法。这种太暴力了。看到这样一段话:

一般这种数对,还涉及排序的,根据第一个元素正向排序,根据第二个元素反向排序,或者根据第一个元素反向排序,根据第二个元素正向排序,往往能够简化解题过程。

2.2. 第一元素反向排序,第二元素正向排序

先按身高(k)从高到低排序,再按大于人数(h)从低到高排序

先排个高的,后面个矮的再怎么排,无论是排个高的前面还是后面,都不会影响到个高的h值。所以先按k降序排。那具体排哪儿呢,只需要排在第h+1个位置,使前面有h个不比他低的人就行。

如果身高相同,h大的人一定在h小的人后边。所以再按h升序排。

如此这般排完序后:[[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]] => [[7,0],[7,1],[6,1],[5,0],[5,2],[4,4]]

(下列计数从0开始计)

排第0个人[7,0] :[ [7,0] ]

排第1个人[7,1]:[ [7,0], [7,1] ] 身高相同,h大的人排h小的人后边

排第2个人[6,1]:[ [7,0], [6,1], [7,1] ] 插入第1个位置,原来在第1个位置的[7,1]变成了第2个位置

排第3个人[5,0]:[ [5,0], [7,0], [6,1], [7,1] ] 插入第0个位置,原来后面的都后移1个位置

排第4个人[5,2]:[ [5,0], [7,0], [5,2], [6,1], [7,1] ] 插入第2个位置

排第5个人[4,4]:[ [5,0], [7,0], [5,2], [6,1], [4,4], [7,1] ] 插入第4个位置

3. 代码

3.1. 超时代码

class Solution {
public:
    const static int MAXN = 1100+5;
    int num,book[MAXN];
    bool flag = false;
    vector<vector<int>> ans;
    //已经排好了q-1位,将原队列第p个人排在新队列第q位是否满足条件
    bool isok(vector<vector<int>>& people, int p, int q){//O(n)
        int cnt = 0;//前q-1位人比第q位身高大于等于的人数
        for(int i=0;i<q;++i){
            if(ans[i][0]>=people[p][0]) cnt++;
        }
        return cnt==people[p][1];
    }
    void dfs(vector<vector<int>>& people, int k){//排第k个人
        if(k==num) {
            flag = true;
            return;
        }
        for(int i=0;i<num;++i){
            if(book[i]) continue;
            if(!isok(people, i, k)) continue;
            ans.push_back(people[i]);
            dfs(people,k+1);
            if(flag) return;
            ans.pop_back();
        }
    }
    bool static cmp(vector<int>& a, vector<int>& b){
        if(a[1]!=b[1]) return a[1]<b[1];
        else return a[0]<b[0];
    }
    vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
        num = people.size();//排队总人数
        sort(people.begin(),people.end(),cmp);
        dfs(people,0);
        return ans;
    }
};

3.2. 先排序再插入代码

class Solution {
public:
    bool static cmp(vector<int>& a, vector<int>& b){
        if(a[0]!=b[0]) return a[0]>b[0];
        else return a[1]<b[1];
    }
    vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
        sort(people.begin(),people.end(),cmp);
        vector< vector<int> > res;
        for(auto& x: people){
            res.insert(res.begin()+x[1],x);
        }
        return res;
    }
};

sort函数部分 lambda函数简化编程:

class Solution {
public:
    vector<vector<int>> reconstructQueue(vector<vector<int>>& people) {
        sort(people.begin(),people.end(),[](const vector<int>& a, const vector<int>& b){
            if(a[0]!=b[0]) return a[0]>b[0];
            else return a[1]<b[1];
        });
        vector< vector<int> > res;
        for(auto& x: people){
            res.insert(res.begin()+x[1],x);
        }
        return res;
    }
};

results matching ""

    No results matching ""