系列文章目录
一、 数组类型解题方法一:二分法
二、数组类型解题方法二:双指针法
三、数组类型解题方法三:滑动窗口
四、数组类型解题方法四:模拟
五、链表篇之链表的基础操作和经典题目
六、哈希表篇之经典题目
七、字符串篇之经典题目
八、字符串篇之 KMP
九、解题方法:双指针
十、栈与队列篇之经典题目
前言
刷题路线来自 :代码随想录
优先级队列(堆):堆可分为大根堆和小根堆,以是数组形式的完全二叉树储存
大根堆
根结点 > 子结点,并且在堆的每一个局部都是如此。如 {3,1,2} 和 {3,2,1} 都为大根堆,大根堆的根结点在整个堆中是最大的元素。
小根堆
根结点 < 子结点。如{ 1,2,3} 和 {1,3,2} 都是小根堆。小根堆的根结点在整个堆中是最小的元素。
题录
215. 数组中的第K个最大元素
Leetcode 链接
给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
示例 1:
输入: [3,2,1,5,6,4] 和 k = 2
输出: 5
示例 2:
输入: [3,2,3,1,2,4,5,5,6] 和 k = 4
输出: 4
题解:
先建一个大根堆,这样第一个数就为最大的数,然后每次和最后一个数交换位置,有效长度减一,再次向下调整为大堆。
class Solution {
public int findKthLargest(int[] nums, int k) {
// 1.建大堆
int end = nums.length - 1;
for (int i = (end - 1) / 2; i >=0; i--) {
// 从最后一个非子叶结点开始向下调整
adjustDown(nums, i,end);
}
// 每次去掉一个最大数
while (k-- > 1) {
// 与最后一个数交换位置
swap(nums, 0, end);
// 有效长度减一
end--;
// 向下调整为大堆
adjustDown(nums, 0, end);
}
return nums[0];
}
// 向下调整
private void adjustDown(int[] array, int parent, int end) {
// 1.找到最大子节点
int child = 2 * parent + 1; // 左孩子
while (child <= end) {
// 找到最大孩子结点
if (child + 1 <= end && array[child + 1] > array[child]) {
// 有右孩子,并且右大于左
child += 1;
}
// 最大孩子结点大于父亲结点,交换位置
if (array[child] > array[parent]) {
swap(array, child, parent);
parent = child;
child = 2 * parent + 1;
} else {
// 已经是大堆,不用调整了
break;
}
}
}
// 交换
private void swap(int[] array, int i, int j) {
int temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
347. 前 K 个高频元素
Leetcode 链接
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
题解: map 记录数组中数字出现次数,使用优先队列(堆),建小堆,遍历 map 依次添加元素进队列,如果队列满了(最大长度 k),出现次数最小的数(队列头元素)出队列
关于怎么确定确定优先级队列比较方法 【(o1, o2) -> o1.getValue() - o2.getValue() 的意思】,看上篇文章:链接
map的遍历:链接
class Solution {
public int[] topKFrequent(int[] nums, int k) {
int[] res = new int[k];
// map 记录数组中数字出现次数
Map<Integer, Integer> map = new HashMap<>();
for (int num : nums) {
map.put(num, map.getOrDefault(num, 0) + 1);
}
// 优先级队列(小根堆)
PriorityQueue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<>((o1, o2) -> o1.getValue() - o2.getValue());
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
queue.add(entry);
if (queue.size() > k) {
queue.poll();
}
}
// 填充返回组中
for (int i = 0; i < k; i++) {
res[i] = queue.poll().getKey();
}
return res;
}
}