20230921刷题记录
参考代码随想录来刷的。
关键词:优先级队列、堆、迭代法二叉树的后序遍历、层序遍历
1 347.前 K 个高频元素
力扣题目链接
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
思路
- 遍历数组,将数组中元素值作为key,元素出现的次数作为value存入map中;
- 使用一个小根堆,小根堆中理应维护的元素是map中的value;
- 遍历map,先将前 k 个 key建立成小根堆;
- 而后一次读入余下的key,若
map.get(key) > map.get(堆顶元素)
,则将堆顶元素删除,将当前key加入堆中。
代码使用优先级队列实现的。
class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++)
map.put(nums[i], map.getOrDefault(nums[i], 0) + 1);
// 创建优先级队列,小根堆实现
PriorityQueue<Integer> priorityQueue = new PriorityQueue<>(Comparator.comparingInt(map::get));
for (Integer key: map.keySet()) {
if (priorityQueue.size() < k){
// 建立一个大小为 k 的小根堆
priorityQueue.offer(key);
} else {
// 判断当前key对应的value是否大于堆顶key对应的value
if (map.get(key) > map.get(priorityQueue.peek())) {
priorityQueue.poll();
priorityQueue.offer(key);
}
}
}
// 小根堆
int[] result = new int[priorityQueue.size()];
for (int i = result.length - 1; i >= 0; i--)
result[i] = priorityQueue.poll();
return result;
}
}
2 145.二叉树的后序遍历
力扣题目链接
注意一下迭代法实现的后序遍历,需要使用一个指针记录右孩子是否被访问过。
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
ArrayDeque<TreeNode> stack = new ArrayDeque<>();
TreeNode p = root;
TreeNode temp = null;
ArrayList<Integer> res = new ArrayList<>();
while (p != null || !stack.isEmpty()) {
if (p != null) {
stack.push(p);
p = p.left;
} else {
p = stack.peek();
if (p.right != null && p.right != temp) {
// p 的右孩子不为空且没有被访问过,才往右走
p = p.right;
} else {
// p 的右孩子为空或者 p 的右孩子已经被访问过了
p = stack.pop();
res.add(p.val);
temp = p;
// 下一个访问的元素在栈顶
p = null;
}
}
}
return res;
}
}
3 102.二叉树的层序遍历
力扣题目链接
每次遍历一层
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if (root == null)
return res;
LinkedList<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
List<Integer> levelList = new ArrayList<>();
int size = queue.size();
for (int i = 0; i < size; i++) {
TreeNode p = queue.poll();
levelList.add(p.val);
if (p.left != null) queue.offer(p.left);
if (p.right != null) queue.offer(p.right);
}
res.add(levelList);
}
return res;
}
}
4 107. 二叉树的层序遍历 II
力扣题目链接
跟上面那道题基本类似,两个解决方案
- 使用链表,以便使用头插法
- 还是用数组,最后遍历数组,倒着取出来
class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
LinkedList<List<Integer>> res = new LinkedList<>();
if (root == null)
return res;
LinkedList<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
List<Integer> levelList = new ArrayList<>();
int size = queue.size();
for (int i = 0; i < size; i++) {
TreeNode p = queue.poll();
levelList.add(p.val);
if (p.left != null) queue.offer(p.left);
if (p.right != null) queue.offer(p.right);
}
res.addFirst(levelList);
}
return res;
}
}
5 199. 二叉树的右视图
力扣题目链接
还是层序遍历,每次遍历一层
class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null)
return res;
LinkedList<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
TreeNode p = null;
for (int i = 0; i < size; i++) {
p = queue.poll();
if (p.left != null) queue.offer(p.left);
if (p.right != null) queue.offer(p.right);
}
res.add(p.val);
}
return res;
}
}