
题目1------二叉树中序遍历
给定一个二叉树的根节点
root,返回 它的 中序 遍历 。示例 1:
输入:root = [1,null,2,3] 输出:[1,3,2]示例 2:
输入:root = [] 输出:[]示例 3:
输入:root = [1] 输出:[1]提示:
- 树中节点数目在范围
[0, 100]内-100 <= Node.val <= 100进阶: 递归算法很简单,你可以通过迭代算法完成吗?
方法肯定是两个递归与迭代
二叉树的中序遍历:按照访问左子树------根节点------右子树的方式遍历这棵树,而在访问左子树或者右子树的时候我们按照同样的方式遍历,直到遍历完整棵树。
递归遍历:
java
// 递归实现
public static void inorder(TreeNode root, List<Integer> res){
if (root == null) {
return;
}
inorder(root.left, res);
res.add(root.val);
inorder(root.right, res);
}
public static List<Integer> inorderTraversal(TreeNode root){
/*
* 递归中序遍历,使用辅助传参数
* */
List<Integer> res = new ArrayList<>();
inorder(root, res);
return res;
}
迭代遍历:
使用栈实现中序遍历
java
public static List<Integer> inorderTraversal02(TreeNode root){
/*
* 使用双向队列栈结构,实现迭代中序遍历
* */
if (root == null){
return new ArrayList<>();
}
List<Integer> res = new ArrayList<>();
Deque<TreeNode> stack = new ArrayDeque<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()) {
while(cur != null) {
stack.push(cur);
cur = cur.left;
}
cur = stack.pop();
res.add(cur.val);
cur = cur.right;
}
return res;
}
题目2------二叉树的最大深度
给定一个二叉树
root,返回其最大深度。二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。
示例 1:
输入:root = [3,9,20,null,null,15,7] 输出:3示例 2:
输入:root = [1,null,2] 输出:2提示:
- 树中节点的数量在
[0, 104]区间内。-100 <= Node.val <= 100
思路:遍历的时候往下走一次就会深度加1,在遍历的基础上维护一个深度。深度优先搜索DFS
递归思路非常快捷:
java
public static int maxDepth(TreeNode root) {
/*
* 递归方法实现,最大深度Math.max(左子树最大深度,右子树最大深度)+1
* */
if (root == null) {
return 0;
}
if (root.left == null && root.right == null) {
return 1;
}
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
迭代思路:使用队列进行,但是要注意要一层一层的处理,而不是单纯的非叶子节点
java
public static int maxDepth(TreeNode root) {
/*
* 迭代方法,使用队列逐层遍历,广度优先搜索
* */
if (root == null) {
return 0;
}
Queue<TreeNode> queue = new ArrayDeque<>();
int ans = 0;
queue.add(root);
while (!queue.isEmpty()) {
// 要弹出一层,塞进下一层
int size = queue.size();
for (int i = 0; i < size; i++) {
// 弹出一层进一层
TreeNode node = queue.poll();
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
ans += 1;
}
return ans;
}
题目3------翻转二叉树
给你一棵二叉树的根节点
root,翻转这棵二叉树,并返回其根节点。示例 1:
输入:root = [4,2,7,1,3,6,9] 输出:[4,7,2,9,6,3,1]示例 2:
输入:root = [2,1,3] 输出:[2,3,1]示例 3:
输入:root = [] 输出:[]提示:
- 树中节点数目范围在
[0, 100]内-100 <= Node.val <= 100
思路:递归翻转,自底向上
java
public TreeNode invertTree(TreeNode root) {
/*
* 递归,自底向上翻转
* */
if (root == null){
return null;
}
if (root.left == null && root.right == null) {
return root;
}
TreeNode cur = root;
TreeNode left = invertTree(cur.left);
TreeNode right = invertTree(cur.right);
cur.right = left;
cur.left = right;
return cur;
}
迭代:层序遍历交换?
java
public TreeNode invertTree(TreeNode root) {
/*
* 递归,自底向上翻转
* */
if (root == null){
return null;
}
if (root.left == null && root.right == null) {
return root;
}
Queue<TreeNode> queue = new ArrayDeque<>();
queue.offer(root);
while (!queue.isEmpty()) {
TreeNode cur = queue.poll();
TreeNode temp = cur.left;
cur.left = cur.right;
cur.right = temp;
if (cur.right != null) {
queue.offer(cur.right);
}
if (cur.left != null) {
queue.offer(cur.left);
}
}
return root;
}
题目4------对称二叉树
给你一个二叉树的根节点
root, 检查它是否轴对称。示例 1:
输入:root = [1,2,2,3,4,4,3] 输出:true示例 2:
输入:root = [1,2,2,null,3,null,3] 输出:false提示:
- 树中节点数目在范围
[1, 1000]内-100 <= Node.val <= 100**进阶:**你可以运用递归和迭代两种方法解决这个问题吗?
思路:
核心思路:把一棵树当成"两棵树"来比较
要判断一棵树是否对称,我们实际上是在判断它的左子树 和右子树是否是相互翻转的(即互为镜像)。
这需要我们写一个辅助函数,同时传入两个节点(左子节点和右子节点),让它们"相向而行"进行比较:
- 左树的左 孩子,要和右树的右孩子比较(外侧边缘)。
- 左树的右 孩子,要和右树的左孩子比较(内侧边缘)。
递归:
递归方法就是需要弄清楚临界条件,核心逻辑就是在u==v的前提下展开,眼看u,v为不为空的具体情况
java
// 递归方法:
public boolean isSymmetric(TreeNode root){
/*
* 翻转树然后比较.按层比较,在翻转的过程中比较,一个正向遍历一个反向遍历比较
* */
if (root == null) {
return true;
}
return check(root, root);
}
public static boolean check(TreeNode u, TreeNode v) {
/*
* 递归检查,一个正向遍历一个反向遍历
* */
// 临界条件
if (u == null && v == null) {
return true;
}
if (u == null || v == null) {
return false;
}
if (u.val != v.val) {
return false;
}
// 核心逻辑
boolean left = check(u.left, v.right);
boolean right = check(u.right, v.left);
return left && right;
}
迭代:
使用LinkedList实现的队列
LinkedList可以存空值,但是ArrayDeque存空值就会报错。
实现类 底层结构 能否存 null 适用场景 ArrayDeque循环数组 ❌ 不能 (报错) 99% 的常规队列/栈需求(速度快、省内存)。 LinkedList双向链表 ✅ 能 你的算法逻辑必须依赖把 null作为占位符放进队列里时。
java
// 使用可以存null的集合LinkedList进行层序遍历
public boolean isSymmetric(TreeNode root){
/*
* 翻转树然后比较.按层比较,在翻转的过程中比较,一个正向遍历一个反向遍历比较
* */
if (root == null) {
return true;
}
return check(root, root);
}
public static boolean check(TreeNode u, TreeNode v) {
/*
* 迭代检查,一个正向遍历一个反向遍历,层序遍历,一个队列即可
* */
Queue<TreeNode> q = new LinkedList<>();
// 一个队列同时正反向遍历两棵树
q.offer(u);
q.offer(v);
while (!q.isEmpty()) {
u = q.poll();
v = q.poll();
// 空的情况
if (u==null&&v==null){
continue;
}
// 不对称的情况
if((u==null||v==null)|| (u.val != v.val)){
return false;
}
// 外侧入队,不用判断空值,因为
q.offer(u.left);
q.offer(v.right);
// 内侧入队
q.offer(u.right);
q.offer(v.left);
}
return true;
}
题目5------二叉树的直径
和最大路径和是同样的解法
给你一棵二叉树的根节点,返回该树的 直径 。
二叉树的 直径 是指树中任意两个节点之间最长路径的 长度 。这条路径可能经过也可能不经过根节点
root。两节点之间路径的 长度 由它们之间边数表示。(边数不是点数了)
示例 1:
输入:root = [1,2,3,4,5] 输出:3 解释:3 ,取路径 [4,2,1,3] 或 [5,2,1,3] 的长度。示例 2:
输入:root = [1,2] 输出:1提示:
- 树中节点数目在范围
[1, 104]内-100 <= Node.val <= 100
思路:基于递归求树高度的方法,最大值维护为左子树高度+右子树高度最大值
tips:最大直径不一定经过根,结果应该所有节点中的(左子树高度+右子树高度)最大值+2
可以将二叉树的直径转换为:二叉树的【每个节点的左右子树的高度和】的最大值
使用递归方法
java
public static int ans = 0;
public static int diameterOfBinaryTree(TreeNode root){
ans = 0;
maxdepth(root);
return ans;
}
public static int maxdepth(TreeNode node){
/*
* 计算一个节点的最大高度,并且在计算过程中,维护,最大的左右子树高度和
* */
if (node==null) {
return 0;
}
int leftdepth = maxdepth(node.left);
int rightdepth = maxdepth(node.right);
int depthSum = leftdepth + rightdepth;
// 维护一个全局变量记录过程中得到左右子树最大高度和
ans = Math.max(ans, depthSum);
return Math.max(leftdepth, rightdepth) + 1;
}
再好好品味下面的困难
题目6------二叉树中的最大路径和
二叉树中的 路径 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。
路径和 是路径中各节点值的总和。
给你一个二叉树的根节点
root,返回其 最大路径和 。示例 1:
输入:root = [1,2,3] 输出:6 解释:最优路径是 2 -> 1 -> 3 ,路径和为 2 + 1 + 3 = 6示例 2:
输入:root = [-10,9,20,null,null,15,7] 输出:42 解释:最优路径是 15 -> 20 -> 7 ,路径和为 15 + 20 + 7 = 42提示:
- 树中节点数目范围是
[1, 3 * 104]-1000 <= Node.val <= 1000
思路和求直径是相同的,只是这次就不是最高度的过程中去维护直径,而是求节点单边最大路径和的情况下,最去维护一个最大拱桥的最大路径和
题目7------二叉树的层序遍历【高频】
给你二叉树的根节点
root,返回其节点值的 层序遍历 。 (即逐层地,从左到右访问所有节点)。示例 1:
输入:root = [3,9,20,null,null,15,7] 输出:[[3],[9,20],[15,7]]示例 2:
输入:root = [1] 输出:[[1]]示例 3:
输入:root = [] 输出:[]提示:
- 树中节点数目在范围
[0, 2000]内-1000 <= Node.val <= 1000
思路就是使用队列来进行层序遍历
进一层出一层,直到队列为空
java
// 这次使用ArrayDeque
public static List<List<Integer>> levelOrder(TreeNode root){
/*
* 使用队列进行层序遍历
* */
if (root == null) {
return new ArrayList<>();
}
Queue<TreeNode> queue = new ArrayDeque<>();
List<List<Integer>> ans = new ArrayList<>();
// 1.根节点入队
queue.offer(root);
while (!queue.isEmpty()){
int size = queue.size();
// 记录每一层结果
List<Integer> layer = new ArrayList<>();
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
layer.add(node.val);
// 放入这个节点的左右子节点
if (node.left!=null) queue.offer(node.left);
if (node.right!=null) queue.offer(node.right);
}
ans.add(layer);
}
return ans;
}









