Queue Reconstruction by Height

探讨了一种根据个体的高度和相对位置信息来重建队列的算法。该算法通过不断选择最高者且前方人数最少的人进行插入,逐步构建出最终的队列。尽管初始方案的时间复杂度为O(n^2),但讨论了可能的优化方向。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Suppose you have a random list of people standing in a queue. Each person is described by a pair of integers (h, k), where h is the height of the person and k is the number of people in front of this person who have a height greater than or equal to h. Write an algorithm to reconstruct the queue.

Note:
The number of people is less than 1,100.

Example

Input:
[[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]

Output:
[[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]]
插入排序的思路

觉得我的代码麻烦了,因为既然是一个个插入我却按照选择高度最高的前提下k值最小的先插入,哎,doubi了,算法复杂度还是O(n^2)

如果事先先按高度和k值先排个序,然而复杂度似乎还是没下降,因为还是得插入

如果用分治算法...

每一个子队列满足这样性质:第i号位置的人person[i]的k值一定大于等于前面比ta高的数量

比如

[[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]
可分为

[[7,0], [4,4], [7,1]]
[[5,0], [6,1], [5,2]]
然后将[5,0][6,1][5,2]依次插入?这样的话合并复杂度是O(n^2),最后复杂度还是O(n^2)

So,有没有办法把合并的复杂度降到O(n),然后使得最后的复杂度降到O(n*log n)?

新生成一个空队列,然后

[7,0][5,0]中选择[5,0]放到队列第一个位置,然后

[7,0]与[6,1],谁在第二个位置?[6,1]不可能,所以第二个位置放[7,0],子队列和新生成的队列是这样的:

[[4,4], [7,1]]
[[6,1], [5,2]]

[[5,0],[7,0]]
[6,1]与[4,4],显然[6,1]放在第3个位置

然后

[[4,4], [7,1]]
[[5,2]]

[[5,0],[7,0],[6,1]]

然后

[[4,4], [7,1]]
[]

[[5,0],[7,0],[6,1],[5,2]]

然后

[]
[]

[[5,0],[7,0],[6,1],[5,2],[4,4],[7,1]]

那么合并的规则是?

[[4,4], [7,1]]
[[6,1], [5,2]]

[[5,0],[7,0]]
[6,1]与[4,4],显然[6,1]放在第3个位置

是经过判断[6,1]与[4,4]哪一个符合的,判断的复杂度又是O(n),这样合并的复杂度还是O(n^2)

有没有办法加强子队列必须满足的性质然后降低合并的复杂度?

还没想到办法

public class Solution {
    public int[][] reconstructQueue(int[][] people) {
        if(people.length == 0) return new int[0][0];
        int[][] re_people = new int[people.length][people[0].length];
        int people_num = people.length;
        int person;
        int max_h;
        int k = people_num;
        int count = 0;
        for(count = 0; count < people_num; ++count){
            max_h = 0;
            k = people_num;
            //select tallest person
            for(person = 0; person < people_num; ++person){
                if(people[person][0] > max_h){  //not visited
                    max_h = people[person][0];
                }
            }
            int select_person = 0;
            for(person = 0; person < people_num; ++person){
                if(people[person][0] == max_h && people[person][1] < k){  //not visited & smallst k
                    k = people[person][1];
                    select_person = person;
                }
            }
            person = select_person;      
            
            //insert the pseron
            int p;
            int place = 0;
            int higher_person_num = 0;

            for(p = 0; p < count; ++p){
            	if(people[person][1] == 0){
            		break;
            	}
            	if(re_people[p][0] >= people[person][0]){
            		++higher_person_num;
            	}
            	if(higher_person_num==people[person][1]){
            		++p;
            		break;
            	}
            }
            
            //shift
            int i;
            for(i = count; i >= p+1; --i){
            	re_people[i][0] = re_people[i-1][0];
            	re_people[i][1] = re_people[i-1][1];
            }
            re_people[p][0] = people[person][0];
            re_people[p][1] = people[person][1];
            people[person][0] = -1;// will not to be visited
        }
        return re_people;
    
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值