1. 题目
给定一个由人群组成的数组 people
,其中每个人以 [hi, ki]
的形式表示,people[i] = [hi, ki]
表示第 i
个人的身高为 hi
,并且前面恰好有 ki
个身高大于或等于 hi
的人。
你需要重新构造并返回一个表示队列的数组 queue
,其中 queue[j] = [hj, kj]
是队列中第 j
个人的属性(queue[0]
是队列最前面的人)。
2. 分析
这个问题的解法是贪心算法,具体步骤如下:
- 排序 :先将所有人按照
h
从高到矮排序,如果h
相同,则按照k
从小到大排序。 - 插入 :从高到矮依次将每个人插入到队列的第
k
个位置上。因为矮的人不会影响到高的人的k
值(即前面比h
高或相等的数量)。
实现原理和解释
为什么排序?
- h 从高到低排序 :这样在插入矮个子时,前面已经插入的都是比他高或相等的人,这样我们可以直接根据
k
值确定插入的位置。 - k 从小到大排序 :如果
h
相同,k
小的人应该放在前面。
为什么插入到 k
的位置?
- 已插入的人更高或等高 :所以对于当前要插入的
[h, k]
,前面的k
个人的h
都 ≥ 当前h
,所以要直接插入到k
的位置。 - 后续插入不影响 :后续插入的都是比当前
h
矮的人,不会影响当前的k
。
为什么能正确构建队列?
- 有序插入策略 :高的人先排好位置,矮的人插在前面不会影响高的人的
k
值。这样能确保每个人的前面恰好有k
个 ≥h
的人。
3. 完整代码
def reconstructQueue(people):
# 按 h 降序,如果 h 相同则按 k 升序 ------后插入的矮个子不会影响已插入的高个子的 k 值。
people.sort(key=lambda x: (-x[0], x[1]))
queue = []
for p in people:
queue.insert(p[1], p) # 将 p 插入到列表 queue 的索引 p[1] 处
return queue
print(reconstructQueue([[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]]
演示:
以 people = [[7,0], [4,4], [7,1], [5,0], [6,1], [5,2]]
为例:
排序后 people = [[7,0], [7,1], [6,1], [5,0], [5,2], [4,4]]
遍历插入过程:
当前 p |
k (插入位置) |
queue 变化 |
解释 |
---|---|---|---|
[7,0] |
0 | [[7,0]] |
插入到第 0 个位置,前面有 0 人 ≥ 7 |
[7,1] |
1 | [[7,0], [7,1]] |
插入到第 1 位置,前面有 1 人 [7,0] ≥ 7 |
[6,1] |
1 | [[7,0], [6,1], [7,1]] |
插入到第 1 位置,前面有 1 人 [7,0] ≥ 6 |
[5,0] |
0 | [[5,0], [7,0], [6,1], [7,1]] |
插入到第 0 位置,前面有 0 人 ≥ 5 |
[5,2] |
2 | [[5,0], [7,0], [5,2], [6,1], [7,1]] |
插入到第 2 位置,前面有 [7,0] , [5,0] ≥ 5 |
[4,4] |
4 | [[5,0], [7,0], [5,2], [6,1], [4,4], [7,1]] |
插入到第 4 位置,前面有 [7,0] , [5,0] , [5,2] , [6,1] ≥ 4 |
在 Python 中,`list.insert(index, element)` 方法不会覆盖原有元素 ,而是会将该索引位置及之后的元素自动后移一位,为新元素腾出空间。这是列表插入操作的核心特性。