文章目录
- 题目--找出一堆随机数中的前 k 大数字
- PriorityQueue 类
- PriorityQueue 常用方法
- 题目--数组中的第 K 个最大元素
题目–找出一堆随机数中的前 k 大数字
找出一堆随机数中的前 k 大
数字,找出一堆随机数中的前 k 小
数字。都一样
方法:快速排序。 最小堆法。
如果不了解堆这个数据结构:点击查看堆
最小堆法:
当数组规模很大时,排序的时间复杂度较高。为了优化,可以使用最小堆(Min-Heap)。在 Java 中可以利用 PriorityQueue
实现一个固定大小为 k 的最小堆来解决问题。
public static void main(String[] args) {
int[] nums = {57, 32, 56, 20, 54, 99, 47, 8, 35, 23, 30, 29, 63, 69, 58};
int k = 5; // 前k大
// 最小堆
PriorityQueue<Integer> minHeap = new PriorityQueue<>(k);
// 遍历数组,维护最小堆
for (int num : nums) {
minHeap.offer(num);
if (minHeap.size() > k) {
minHeap.poll(); // 移除堆顶 即数组第一个元素
}
}
System.out.println("前 " + k + " 大的数: ");
while (!minHeap.isEmpty()) {
System.out.print(minHeap.poll() + " ");
}
}
PriorityQueue 类
PriorityQueue
是 Java 中实现堆(Heap)
数据结构的一个重要类,它基于优先级队列(Priority Queue)的概念。它使用堆来实现,默认是最小堆,即堆顶是队列中最小的元素。也可以通过传递自定义的比较器来实现最大堆。
PriorityQueue的底层实现是使用一个数组
来进行节点的存储
PriorityQueue 默认最小堆:
优先级队列表示为平衡二叉堆:queue[n] 的两个子节点为queue[2n+1] 和queue[2(n+1)]。优先级队列按比较器排序,如果比较器为空,则按元素的自然顺序排序:对于堆中的每个节点 n 和 n 的每个后代 d,n <= d。假设队列非空,则具有最小值的元素位于queue[0]中。【默认最小堆】
PriorityQueue 实现大根堆:
大根堆,则数组第一个元素最大
new PriorityQueue<>(Comparator.reverseOrder())
传入一个参数即可
public static void main(String[] args) {
// 自定义比较器,将 PriorityQueue 变为最大堆
PriorityQueue<Integer> maxHeap = new PriorityQueue<>(Comparator.reverseOrder());
maxHeap.offer(10);
maxHeap.offer(40);
maxHeap.offer(20);
maxHeap.offer(30);
System.out.println("最大堆中的元素:");
while (!maxHeap.isEmpty()) {
System.out.print(maxHeap.poll() + " "); // 输出时将从大到小
}
}
PriorityQueue 的特性:
-
自动排序:
PriorityQueue
会根据元素的优先级自动排序,默认排序方式是最小堆,意味着堆顶元素是队列中最小的元素。- 如果需要实现最大堆,可以传入一个自定义的比较器,使得元素按照降序排列。
-
不允许
null
元素:PriorityQueue
不允许插入null
元素,否则会抛出NullPointerException
。
-
线程不安全:
PriorityQueue
不是线程安全的。如果需要在多线程环境下使用,可以使用PriorityBlockingQueue
。
-
时间复杂度:
- 插入(
offer()
)和删除最小元素(poll()
)的时间复杂度均为O(log n)
,其中n
是队列的大小。 - 获取队列中最小元素的时间复杂度是
O(1)
,即通过peek()
方法。
- 插入(
PriorityQueue 常用方法
方法名 | 描述 |
---|---|
add(E e) | 插入元素 e 到队列中,若违反队列容量限制,抛出 IllegalStateException 。 |
offer(E e) | 插入元素 e 到队列中,返回 true 表示插入成功,若违反容量限制返回 false 。 |
poll() | 获取并移除队列的堆顶元素(即最小元素),若队列为空则返回 null 。 |
peek() | 获取但不移除队列的堆顶元素(即最小元素),若队列为空则返回 null 。 |
remove(Object o) | 从队列中移除指定的元素 o 。 |
isEmpty() | 检查队列是否为空。 |
size() | 返回队列的元素个数。 |
clear() | 清空队列中的所有元素。 |
contains(Object o) | 检查队列中是否包含指定的元素 o 。 |
题目–数组中的第 K 个最大元素
这个题也可以利用 PriorityQueue
秒了
public int findKthLargest(int[] nums, int k) {
PriorityQueue<Integer> queue = new PriorityQueue<>();
for (int num : nums) {
queue.offer(num);
if (queue.size() > k) {
queue.poll();
}
}
return queue.peek();
}
❤觉得有用的可以留个关注~❤