二叉树

(1)二叉树的中序遍历:

题目链接🍳

算法思路:

使用递归实现的二叉树中序遍历算法,按照 “左子树 → 根节点 → 右子树” (LNR)的顺序遍历所有节点,并将节点的值收集到一个列表中返回(因为返回值类型为List<Integer>)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
inorder(root, res);
return res;
}

public void inorder(TreeNode root, List<Integer> res){
if(root == null){
return;
}
inorder(root.left, res);
res.add(root.val);
inorder(root.right, res);
}
}

(2)二叉树的最大深度

题目链接🍳

算法思路:

深度优先搜索:在计算当前二叉树的最大深度时,可以先递归计算出其左子树和右子树的最大深度,整个二叉树的最大深度就是根节点的左右子树中,深度最大的值+1

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public int maxDepth(TreeNode root) {
if(root == null){
return 0;
}else{
int L1 = maxDepth(root.left);
int L2 = maxDepth(root.right);
return (L1 > L2 ? L1 : L2) + 1;
}

}

}

(3)翻转二叉树

题目链接🍳

算法思路:

从根节点开始,递归地对树进行遍历,并从叶子节点先开始翻转。如果当前遍历到的节点 root 的左右两棵子树都已经翻转,那么我们只需要交换两棵子树的位置,即可完成以 root 为根节点的整棵子树的翻转。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root == null){
return null;
}
TreeNode left = invertTree(root.left);
TreeNode right = invertTree(root.right);
//没有后面两句,前面两句就是单纯复制了一下,方法二可能更符合递归的逻辑
root.left = right;
root.right = left;
return root;

}
}

//方法二:创建新结点
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) {
return null;
}
//不创建新结点,会导致root.left值改了又进入到root.right的参数里面
TreeNode newNode = new TreeNode(root.val);

// 关键:左右交换!
newNode.left = invertTree(root.right); // 原右→新左
newNode.right = invertTree(root.left); // 原左→新右

return newNode;
}
}

注意:翻转二叉树得到的结果是翻转前的二叉树与翻转后的二叉树是镜像对称的image-20260128225301230

(4)对称二叉树

题目链接🍳:对称二叉树

算法思路:

此题目的二叉树是镜像对称的。满足下面两个条件,则二叉树为对称二叉树:

  • 根节点的左右孩子分别为两个二叉树,这两个二叉树的两个根节点具有相同的值
  • 每个树的右子树与另一个树的左子树镜像对称
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public boolean isSymmetric(TreeNode root) {
return check(root.left, root.right);
}

public boolean check(TreeNode p, TreeNode q) {
//判度两个二叉树是否是镜像对称
if (p == null && q == null) {
return true;
}
if (p == null || q == null) {
return false;
}
return p.val == q.val && check(p.left, q.right) && check(p.right, q.left);

}
}

==补充:==基于第三题,我有了个新的想法:(可以先翻转左子树,然后判断翻转后的左子树与右子树是否完全相同本质一样有点脱裤子放屁了🎈

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

//先翻转左子树,然后判断翻转后的左子树与右子树是否完全相同
class Solution {
public boolean isSymmetric(TreeNode root) {
TreeNode invertLeft = invertTree(root.left);
return isSameTree(invertLeft, root.right);
}

//翻转二叉树
private TreeNode invertTree(TreeNode node) {
if (node == null) return null;
TreeNode newNode = new TreeNode(node.val);//创建新结点不改变原来的树
//和第三题不同的是:创建新节点时就已经按翻转的顺序构建子树
newNode.left = invertTree(node.left);
newNode.right = invertTree(node.right);
return newNode;
}

private boolean isSameTree(TreeNode p, TreeNode q) {
if (p == null && q == null) {
return true;
}
if (p == null || q == null) {
return false;
}
if(p.val != q.val ){
return false;
}

return isSameTree(p.left, q.right) && isSameTree(p.right, q.left);
}
}

(5)二叉树的直径

题目链接🍳:二叉树的直径

算法思路:

在第(2)题中,求二叉树的深度,就是运用深度优先搜索,找出二叉树左右子树中深度最大的再+1(加根节点的深度)就是整个二叉树的深度。(例如下面的图中,二叉树的深度是5);

此题求二叉树的直径,例如下图中,路径最长的路径[9 -> 4 -> 2 -> 5 -> 7 -> 8] 路径长度为5,正好等于路径上的结点数-1。第二题中,得到了如何求二叉树的深度,前面举得例子中,路径上结点的总数等于以2为根节点的左右子树的深度和加1(下图2+3+1);设结点总数为ansimage-20260120152844405

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
int ans = 0;
public int diameterOfBinaryTree(TreeNode root) {
depth(root);
return ans - 1; //路径长度等于路径上结点数目减去1
}

public int depth(TreeNode node) {
if (node == null) {
return 0;
}

int L = depth(node.left); //左子树的深度
int R = depth(node.right); //右子树的深度

ans = Math.max(ans, L + R + 1); //路径上结点的总数

return Math.max(L, R) + 1;
}
}