今天是 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
。
即使不是所有人都是同一高度,这个策略也是可行的。因为个子矮的人相对于个子高的人是 “看不见” 的(这点很关键也很扎心,有没有?)所以可以先安排个子高的人。
上图中我们先安排身高为 7
的人,将它放置在与 k
值相等的索引上;再安排身高为 6
的人,同样的将它放置在与 k
值相等的索引上。
该策略可以递归进行:
将最高的人按照 k 值升序排序,然后将它们放置到输出队列中与 k 值相等的索引位置上。按降序取下一个高度,同样按 k 值对该身高的人升序排序,然后逐个插入到输出队列中与 k 值相等的索引位置上。直到完成为止。
代码实现
//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
元红包一个!