一、题目描述
假设有打乱顺序的一群人站成一个队列,数组 people
表示队列中一些人的属性(不一定按顺序)。每个 people[i] = [hi, ki]
表示第 i
个人的身高为 hi
,前面 正好 有 ki
个身高大于或等于 hi
的人。
请你重新构造并返回输入数组 people
所表示的队列。返回的队列应该格式化为数组 queue
,其中 queue[j] = [hj, kj]
是队列中第 j
个人的属性(queue[0]
是排在队列前面的人)。
示例 1:
输入:people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]] 输出:[[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]] 解释: 编号为 0 的人身高为 5 ,没有身高更高或者相同的人排在他前面。 编号为 1 的人身高为 7 ,没有身高更高或者相同的人排在他前面。 编号为 2 的人身高为 5 ,有 2 个身高更高或者相同的人排在他前面,即编号为 0 和 1 的人。 编号为 3 的人身高为 6 ,有 1 个身高更高或者相同的人排在他前面,即编号为 1 的人。 编号为 4 的人身高为 4 ,有 4 个身高更高或者相同的人排在他前面,即编号为 0、1、2、3 的人。 编号为 5 的人身高为 7 ,有 1 个身高更高或者相同的人排在他前面,即编号为 1 的人。 因此 [[5,0],[7,0],[5,2],[6,1],[4,4],[7,1]] 是重新构造后的队列。
示例 2:
输入:people = [[6,0],[5,0],[4,0],[3,2],[2,2],[1,4]] 输出:[[4,0],[5,0],[2,2],[3,2],[1,4],[6,0]]
提示:
1 <= people.length <= 2000
0 <= hi <= 10^6
0 <= ki < people.length
- 题目数据确保队列可以被重建
二、解题思路
-
首先对数组
people
进行排序。排序规则是:首先按照身高hi
降序排序,如果身高相同,则按照ki
升序排序。这样做的原因是身高高的人对于身高矮的人是“不可见”的,因此我们先安排身高高的人,这样在插入身高矮的人时,就可以忽略身高高的人。 -
创建一个空的列表
queue
,用于存放最终的队列。 -
遍历排序后的
people
数组,根据每个人的ki
值,将其插入到queue
中的相应位置。由于身高高的人已经先被插入,所以身高矮的人插入时,只需保证前面有ki
个身高大于或等于他的人即可。 -
返回
queue
作为结果。
三、具体代码
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
class Solution {
public int[][] reconstructQueue(int[][] people) {
// 按照身高降序,如果身高相同则按照ki升序排序
Arrays.sort(people, (a, b) -> {
if (a[0] == b[0]) return a[1] - b[1];
return b[0] - a[0];
});
// 创建一个空的列表用于存放最终的队列
List<int[]> queue = new LinkedList<>();
// 遍历排序后的people数组,根据ki值插入到队列中的相应位置
for (int[] person : people) {
queue.add(person[1], person);
}
// 将列表转换为数组并返回
return queue.toArray(new int[people.length][2]);
}
}
这段代码首先对 people
数组进行排序,然后创建一个 LinkedList
来模拟队列的插入操作,最后将 LinkedList
转换为数组并返回。由于 LinkedList
的 add
方法可以在指定位置插入元素,这正好符合题目中 ki
的要求。
四、时间复杂度和空间复杂度
1. 时间复杂度
-
排序操作:
Arrays.sort
方法使用了双轴快速排序算法,其平均时间复杂度为 O(n log n),其中 n 是数组people
的长度。 -
遍历操作:对排序后的
people
数组进行遍历,这一步的时间复杂度为 O(n)。 -
插入操作:在
LinkedList
中插入元素的操作时间复杂度为 O(1),但由于每次插入可能需要移动后续元素,因此总的时间复杂度取决于插入的位置。在最坏情况下,每次插入都发生在列表的开始位置,这样每次插入的时间复杂度将是 O(n)。因此,插入操作的总时间复杂度为 O(n^2)。
综上所述,总的时间复杂度为 O(n log n) + O(n^2) = O(n^2),因为 O(n^2) 是主导项。
2. 空间复杂度
-
排序操作:由于在原地对数组进行排序,所以除了输入数组外,不需要额外的空间,空间复杂度为 O(1)。
-
队列操作:创建了一个
LinkedList
来存放最终的队列,其空间复杂度为 O(n),其中 n 是数组people
的长度。 -
返回数组:最后将
LinkedList
转换为数组,这个操作需要 O(n) 的空间来存放结果。
因此,总的空间复杂度为 O(n),这是因为除了输入数组外,我们需要额外的空间来存储队列和最终的结果数组。
五、总结知识点
-
Java 类定义:
class Solution
定义了一个名为Solution
的类。
-
方法定义:
public int[][] reconstructQueue(int[][] people)
定义了一个公共方法reconstructQueue
,它接受一个二维整数数组people
作为参数,并返回一个二维整数数组。
-
数组排序:
Arrays.sort
方法用于对数组进行排序。- 使用 lambda 表达式
(a, b) -> {...}
定义了一个自定义的比较器,用于排序规则。
-
Lambda 表达式:
(a, b) -> {...}
是一个 lambda 表达式,它定义了如何比较两个数组元素。
-
逻辑运算:
if (a[0] == b[0]) return a[1] - b[1];
和return b[0] - a[0];
中的条件判断和返回语句。
-
数据结构:
LinkedList<int[]> queue
创建了一个LinkedList
,用于动态地存储队列。
-
列表操作:
queue.add(person[1], person);
使用LinkedList
的add
方法在指定索引处插入元素。
-
循环遍历:
for (int[] person : people)
是一个增强型 for 循环,用于遍历数组people
。
-
类型转换:
queue.toArray(new int[people.length][2]);
将LinkedList
转换为二维整数数组。
-
方法返回值:
return queue.toArray(new int[people.length][2]);
返回了重构后的队列。
以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。
标签:队列,people,--,复杂度,queue,406,数组,身高,LeetCode From: https://blog.csdn.net/weixin_62860386/article/details/143870088