2020_11_16 每日一题 406. 根据身高重建队列

假设有打乱顺序的一群人站成一个队列。 每个人由一个整数对(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

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

没有思路去看答案了…

循序渐进的思路
如果我们拿到的是一个没有重复身高的,按身高升序排列的数组我们应该怎么办?结果数组一开始为空,一个一个往里扔。那我们知道,当我们再往里扔一个人(身高为h,前方比他高的有k个)的时候,已经在数组里的都比我矮,不能算比我高的计数;之后往里扔的都比我高,一定会算作计数,那我只需要在前方有k给空位就好了,这样可以在O(n2)的时间完成目标
有身高相同的人会带来什么不同?
那样就不仅仅是前面的空位,前面的和我身高一样的也会带来计数。
首先考虑,是否可能有两个身高相同,前方比他们高的人数也相同?简单反证法可知不可能。
这样在往里加的时候就可以从k最大的加起,k比他小,且身高相同的会加在它的左边,也会带来计数。如果先从k小的加起,在给k大的找位置的时候就需要将h相同的也加入计数了。代码:

class Solution {
    public int[][] reconstructQueue(int[][] people) {
        //看题解看明白
        int n = people.length;
        int[][] ret = new int[n][];
        Arrays.sort(people, (a, b) -> a[0]- b[0] == 0 ? b[1] -a[1] : a[0] - b[0]);//先按身高 再按比它高的数量升序排列
        for(int i = 0; i < n;) {
            int j = i + 1;
            while(j < n && people[i][0] == people[j][0]) {
                ++j;//[i, j)的身高相同
            }
            while(i < j) {
                int t = 0, index = 0;
                while(t < people[i][1]) {
                    if(ret[index] == null) {
                        ++t;
                    }
                    ++index;
                }
                while(ret[index] != null) {
                    ++index;
                }
                ret[index] = people[i];
                ++i;
            }
        }
        return ret;
    }
}

如果一开始数组降序排列呢?
那么在加一个人的时候,只要看当前队列里有多少人就好了。这时候身高相同的需要升序排列,否则后加的会影响先加的。代码:

class Solution {
    public int[][] reconstructQueue(int[][] people) {
        //看题解看明白
        int n = people.length;
        Arrays.sort(people, (a, b) -> a[0]- b[0] == 0 ? a[1] - b[1] : b[0] - a[0]);//先按身高降序 再按比它高的数量升序排列
        ArrayList<int[]> ret = new ArrayList<>();
        for(int[] p : people) {
            ret.add(p[1], p);
        }
        for(int i = 0; i < n; ++i){
            people[i] = ret.get(i);
        }
        return people;
    }
}

java的ArrayList的add()似乎能够实现均摊O(1)的时间复杂度,也不知道怎么实现的
如果把均摊当O(1)的化这种方法是O(nlgn)(排序),比第一个快

你可能感兴趣的:(每日一题,leetcode)