406. 根据身高重建队列

题目链接
分析:题目意思是要我们将一个数组 people[i] = {h,k},放到一个位置,并且能保证,这个位置前面有k个h大于等于当前h的。
首先说一下需要使用到的变量:

res[][]:用来记录最终答案的二维数组
vis[]:用来记录这个位置是否已经放置了元素
count:用来记录前面有几个大于等于当前h的元素

那么我们可以反过来想,首先找到一个最小的h,那么其它的h肯定比当前大,那么只需要考虑前面有k个位置就行,也就是说,当前这个放到第k+1个位置就行。(这里为了简单,先没考虑有相同的h)

下面我们再考虑有相同h的情况。
其实也很好考虑。
我们从res的第0个开始遍历,当count还小于k的时候,那么说明还要继续往后遍历,因为还没找到合适的位置。
那么什么时候count自增呢,也就是说,什么时候才叫找到了一个大于等于当前h的位置呢?
第一:遍历到当前位置没有被访问,因为每次我们都需要拿出people中剩下的最小的,所以,还没有被访问的肯定是放后面元素的,所以肯定是大于等于当前h的,此时count+1.
第二:遍历到元素等于当前h,也就是有相同h存在的情况,此时也是count+1。

直到People都放到了res即可。

那么此时还有两个问题
问题一:就是我们每次怎么去找h最小的?
问题二:并且如果当前剩下的people中最小的h有多个,应该选择哪一个?

问题一:
我们可以将people放到小顶堆中,这样每次拿到的就是h最小的。
问题二:
如果h相同,那么我们应该选择k最小的,因为h相同,k最小的肯定放在前面。

代码:

class Solution {
    public int[][] reconstructQueue(int[][] people) {
        //小顶堆 h小的放上面, h相同则k小的放上面
        Queue<int[]> queue = new PriorityQueue<>((i1,i2)->{
            if(i1[0]!=i2[0]){
                return i1[0]-i2[0];
            }else{
                return i1[1]-i2[1];
            }
        });

        int n = people.length;
        int[][] res = new int[n][2];
        //记录这个位置是否被访问过
        boolean[] vis = new boolean[n];
        for(int i=0; i<n; i++){
            queue.offer(people[i]);
        }
        while(!queue.isEmpty()){
            int[] top = queue.poll();
            int count=0;
            int i=0;
            while(i<n && count<top[1]){
                //这个位置没被访问过  或者   这个位置访问过了,但是h相等
                if(!vis[i] || res[i][0]==top[0]){
                    count++;
                }
                i++;
            }
            while(vis[i]){
                i++;
            }
            res[i] = top;
            vis[i] = true;
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值