深度优先遍历

要掌握深度优先遍历,必须掌握递归的使用;

递归的本质:

递归通常包括两部分:

  1. 基本情况(非常重要):定义问题最小的,不再需要递归的情况,这是递归终止的条件

  2. 将问题划分为更小规模的子问题,并通过调用自身来解决这些子问题

只要基本情况写对,就要有充分理由相信递归一定能实现,这就是递归的“信仰飞跃”

1.三种遍历

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// 前序遍历·递归·LC144_二叉树的前序遍历
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
preorder(root, result);
return result;
}

public void preorder(TreeNode root, List<Integer> result) {
if (root == null) {
return;
}
result.add(root.val);
preorder(root.left, result);
preorder(root.right, result);
}
}
// 中序遍历·递归·LC94_二叉树的中序遍历
class Solution {
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
inorder(root, res);
return res;
}

void inorder(TreeNode root, List<Integer> list) {
if (root == null) {
return;
}
inorder(root.left, list);
list.add(root.val); // 注意这一句
inorder(root.right, list);
}
}
// 后序遍历·递归·LC145_二叉树的后序遍历
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
postorder(root, res);
return res;
}

void postorder(TreeNode root, List<Integer> list) {
if (root == null) {
return;
}
postorder(root.left, list);
postorder(root.right, list);
list.add(root.val); // 注意这一句
}
}

2.翻转二叉树,镜像翻转

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public TreeNode invertTree(TreeNode root) {
if(root==null){
return null;
}
// 要明确的是 invertTree返回的是反转好的节点,所有直接赋值给left和right
TreeNode left = invertTree(root.left);
TreeNode right = invertTree(root.right);
root.left = right;
root.right = left;
return root;
}
}

257.二叉树的所有路径

给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。

叶子节点 是指没有子节点的节点。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public List<String> binaryTreePaths(TreeNode root) {
// 后序遍历
List<String> paths = new ArrayList<String>();
constructPaths(root,"",paths);
return paths;
}
public void constructPaths(TreeNode root ,String path , List<String> paths){
if(root!=null){
StringBuilder pathSB = new StringBuilder(path);
pathSB.append(Integer.toString(root.val));
if(root.left==null && root.right==null){
paths.add(pathSB.toString());
}else{
pathSB.append("->");
constructPaths(root.left , pathSB.toString(),paths); // 要理解这个的意义是路径
constructPaths(root.right , pathSB.toString(),paths);
}
}
}
}

112. 路径总和

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false

叶子节点 是指没有子节点的节点。

1
2
3
4
5
6
7
8
9
10
11
12
13
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if(root==null){
return false;
}
if(root.left == null && root.right == null){
return targetSum == root.val;
}
return hasPathSum(root.left , targetSum-root.val) || hasPathSum(root.right,targetSum-root.val); // 要明确hasPathSum()的作用是求路径总和

}

}