携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第12天,点击查看活动详情 >>
每日三刷,剑指千题
计划简介:
- 每日三题,以中等题为主,简单题为辅进行搭配。保证质量题1道,数量题3道。
- 每日早通勤在LeetCode手机端选题,思考思路,没答案的直接看题解。
- 每日中午进行编码,时间控制在一小时之内。
- 下班前半小时进行整理总结,并发布到掘金每日更文活动。
说明:
- 基于以前的刷题基础,本次计划以中等题为主,大部分中等题都可以拆分为多个简单题,所以数量保证3,质量保证一道中等题即可。
- 刷题顺序按照先刷链表、二叉树、栈、堆、队列等基本数据结构,再刷递归、二分法、排序、双指针等基础算法,最后是动态规划、贪心、回溯、搜索等复杂算法。
- 刷题过程中整理相似题型,刷题模板。
- 目前进度 142/1000 。
[662]二叉树最大宽度
给定一个二叉树,编写一个函数来获取这个树的最大宽度。树的宽度是所有层中的最大宽度。这个二叉树与满二叉树(full binary tree) 结构相同,但一些节点为空。
每一层的宽度被定义为两个端点(该层最左和最右的非空节点,两端点间的null节点也计入长度)之间的长度。
示例 1:
输入:
1
/ \
3 2
/ \ \
5 3 9
输出: 4
解释: 最大值出现在树的第 3 层,宽度为 4 (5,3,null,9)。
解析
考虑了半天层序遍历,发现不行,毁在了“两端点间的null节点也计入长度”这个条件。
那猜测应该是DFS,但是怎么写没想起来,看一下解析吧。
忽略了题目的一句话:这个二叉树与满二叉树(full binary tree) 结构相同。顺着满二叉树的思考下去:
主要想法是给每个节点一个 position 值,如果我们走向左子树,那么 position -> position * 2,如果我们走向右子树,那么 position -> positon * 2 + 1。当我们在看同一层深度的位置值 L 和 R 的时候,宽度就是 R - L + 1。
Code
class Solution {
Map<Integer, Integer> left = new HashMap<>();
int ans = 0;
public int widthOfBinaryTree(TreeNode root) {
dfs(root, 0, 0);
return ans;
}
private void dfs(TreeNode root, int depth, int pos) {
if (root == null) return;
// 最左端,不能覆盖
left.computeIfAbsent(depth, x->pos);
ans = Math.max(ans, pos - left.get(depth) + 1);
dfs(root.left, depth + 1, pos * 2);
dfs(root.right, depth + 1, pos * 2 + 1);
}
}
[100]相同的树
给你两棵二叉树的根节点 p 和 q ,编写一个函数来检验这两棵树是否相同。
如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。
示例 1:
输入:p = [1,2,3], q = [1,2,3]
输出:true
解析
递归遍历,加上条件判断就可以了。
就用前序遍历吧,
Code
class Solution {
boolean ans = true;
public boolean isSameTree(TreeNode p, TreeNode q) {
dfs(p, q);
return ans;
}
private void dfs(TreeNode p, TreeNode q) {
if (p == null & q == null) {
return;
} else if (p == null || q == null) {
ans = false;
} else {
if (p.val != q.val) ans = false;
dfs(p.left, q.left);
dfs(p.right, q.right);
}
}
}
[652]寻找重复的子树
给定一棵二叉树 root,返回所有重复的子树。
对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可。
如果两棵树具有相同的结构和相同的结点值,则它们是重复的。
示例 1:
输入:root = [1,2,3,4,null,2,4,null,null,4]
输出:[[2,4],[4]]
解析
使用深度优先搜索,其中递归函数返回当前子树的序列化结果。把每个节点开始的子树序列化结果保存在 ma**p 中,然后判断是否存在重复的子树。
对有返回值的递归理解的更深刻了。
Code
class Solution {
List<TreeNode> ans = new ArrayList<>();
Map<String, Integer> count = new HashMap();
public List<TreeNode> findDuplicateSubtrees(TreeNode root) {
dfs(root);
return ans;
}
private String dfs(TreeNode root) {
if (root == null) return "";
String left = dfs(root.left);
String right = dfs(root.right);
String key = root.val + "," + left + "," + right;
count.put(key, count.getOrDefault(key, 0) + 1);
if (count.get(key) == 2) {
ans.add(root);
}
return key;
}
}
\