假设有搅乱顺序的一群儿童成一个队列_一日一力扣第55天:根据身高重建队列...

今天是 Kevin 的算法之路的第 55 天。为大家讲解 LeetCode 第 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 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

这道题的题意和思路都有点难懂,希望你能静下来和我一步一步解决。

首先我觉得这个题意大概是某翻译的结果,反正我读了几遍都没读懂。大概是我笨,所以再翻译一遍:

{"person":(h,k).....}
其中h是这个人的身高,k是排在这个人前面且身高大于或等于h的人数
排序这个字典,使之位置符合h,k
输出list

至于思路,我们先从最简单的情况下思考,

当队列中所有人的 (h,k) 都是相同的高度 h,只有 k 不同时,解决方案很简单:每个人在队列的索引 index = k

1f944908d2439cff8c47bb84b83be77c.png

即使不是所有人都是同一高度,这个策略也是可行的。因为个子矮的人相对于个子高的人是 “看不见” 的(这点很关键也很扎心,有没有?)所以可以先安排个子高的人。

0f3d456fc230f6e52e71c9b46f4fd065.png

上图中我们先安排身高为 7 的人,将它放置在与 k 值相等的索引上;再安排身高为 6 的人,同样的将它放置在与 k 值相等的索引上。

该策略可以递归进行:

将最高的人按照 k 值升序排序,然后将它们放置到输出队列中与 k 值相等的索引位置上。按降序取下一个高度,同样按 k 值对该身高的人升序排序,然后逐个插入到输出队列中与 k 值相等的索引位置上。直到完成为止。

71d1df661be0714dab63497627823cd2.png

代码实现

//go

import (
 "sort"
)

func reconstructQueue(people [][]int) [][]int {
 // 排序,先按照身高h排序,如果身高一样高,那就按照人数k排序
 sort.Slice(people, func(i, j int) bool {
  return (people[i][0] > people[j][0]) || (people[i][0] == people[j][0] && people[i][1] 1])
 })

 // 按照k值插入到index=k的地方,index之后的往后移动
 for i, p := range people {
  copy(people[p[1]+1:i+1], people[p[1]:i+1]) // 将index之后的复制到index+1
  people[p[1]] = p // 将p插入到index位置
 }

 return people
}
//java
class Solution {
  public int[][] reconstructQueue(int[][] people) {
    Arrays.sort(people, new Comparator<int[]>() {
      @Override
      public int compare(int[] o1, int[] o2) {
        // if the heights are equal, compare k-values
        return o1[0] == o2[0] ? o1[1] - o2[1] : o2[0] - o1[0];
      }
    });

    List<int[]> output = new LinkedList<>();
    for(int[] p : people){
      output.add(p[1], p);
    }

    int n = people.length;
    return output.toArray(new int[n][2]);
  }
}

郑重声明:

所展示代码已通过 LeetCode 运行通过,请放心食用~

在唠唠嗑

很多人都想养成好习惯,但大多数人却是三分钟热度。为了我们能一起坚持下去,决定制定如下计划(福利)

一起学算法,打卡领红包!

参与方式:

关注我的微信公众号「Kevin的学堂」

还可「加群」与众多小伙伴

一起坚持,一起学习,一起更优秀!

打卡规则为:

「留言」“打卡XXX天” ➕「分享」到朋友圈

奖励:

打卡 21 天,联系本人获取 6.6 元红包一个!

打卡 52 天,联系本人获取 16.6 元红包一个!

打卡 100 天,联系本人获取 66.6 元红包一个!

52c15b9df38d7e8757264f77400d3a99.png
长按扫码,一起进步
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值