二叉树
# 144. 二叉树的前序遍历 - 力扣(LeetCode) (opens new window)
# 递归
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
preOrder(root, res);
return res;
}
public void preOrder(TreeNode root,List<Integer> res){
if (root == null) {
return;
}
res.add(root.val);
preOrder(root.left,res);
preOrder(root.right,res);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 非递归
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) {
return res;
}
Deque<TreeNode> stack = new LinkedList<TreeNode>();
TreeNode node = root;
while (!stack.isEmpty() || node != null) {
while (node != null) {
res.add(node.val);
stack.push(node);
node = node.left;
}
node = stack.pop();
node = node.right;
}
return res;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 94. 二叉树的中序遍历 - 力扣(LeetCode) (opens new window)
# 递归
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);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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>();
Deque<TreeNode> stack = new LinkedList<TreeNode>();
while (!stack.isEmpty() || root != null) {
while (root != null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
res.add(root.val);
root = root.right;
}
return res;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 145. 二叉树的后序遍历 - 力扣(LeetCode) (opens new window)
# 递归
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
postOrder(root, res);
return res;
}
public void postOrder(TreeNode root,List<Integer> res) {
if (root == null) {
return;
}
postOrder(root.left,res);
postOrder(root.right,res);
res.add(root.val);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 非递归
class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) {
return res;
}
Deque<TreeNode> stack = new LinkedList<TreeNode>();
TreeNode prev = null;
while (root!=null || !stack.isEmpty()) {
while (root != null) {
stack.push(root);
root = root.left;
}
root = stack.pop();
if (root.right == null || root.right == prev) {
res.add(root.val);
prev = root;
root = null;
} else {
stack.push(root);
root = root.right;
}
}
return res;
}
}
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
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
# 102. 二叉树的层序遍历 - 力扣(LeetCode) (opens new window)
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> ans = new ArrayList<List<Integer>>();
if (root == null) {
return ans;
}
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
while (!queue.isEmpty()) {
List<Integer> level = new ArrayList<Integer>();
int currentLevelSize = queue.size();
for (int i = 1;i <= currentLevelSize; ++i) {
TreeNode node = queue.poll();
level.add(node.val);
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
ans.add(level);
}
return ans;
}
}
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
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
# 103. 二叉树的锯齿形层序遍历 - 力扣(LeetCode) (opens new window)
class Solution {
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> ans = new ArrayList<List<Integer>>();
if (root == null) {
return ans;
}
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
boolean orderLeft = true;
while (!queue.isEmpty()) {
Deque<Integer> level = new LinkedList<Integer>();
int currentLevelSize = queue.size();
for (int i = 1;i <= currentLevelSize; ++i) {
TreeNode node = queue.poll();
if (orderLeft) {
level.offerLast(node.val);
}else{
level.offerFirst(node.val);
}
if (node.left != null) {
queue.offer(node.left);
}
if (node.right != null) {
queue.offer(node.right);
}
}
ans.add(new LinkedList<Integer>(level));
orderLeft =! orderLeft;
}
return ans;
}
}
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
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
# 105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode) (opens new window)
class Solution {
HashMap<Integer, Integer> valToIndex = new HashMap<>();
public TreeNode buildTree(int[] preorder, int[] inorder) {
for (int i = 0;i < inorder.length; i++) {
valToIndex.put(inorder[i],i);
}
return build(preorder, 0, preorder.length - 1, inorder, 0, inorder.length - 1);
}
TreeNode build(int[] preorder,int preStart,int preEnd,int[] inorder,int intStart,int inEnd) {
if (preStart > preEnd) {
return null;
}
int rootVal = preorder[preStart];
int index = valToIndex.get(rootVal);
// int index = 0;
// for (int i = intStart;i <= inEnd; i++) {
// if (inorder[i] == rootVal) {
// index = i;
// break;
// }
// }
TreeNode root = new TreeNode(rootVal);
int leftSize = index - intStart;
root.left = build(preorder, preStart + 1, preStart + leftSize, inorder, intStart, index - 1);
root.right = build(preorder, preStart + leftSize + 1, preEnd, inorder, index + 1, inEnd);
return 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
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
# 236. 二叉树的最近公共祖先 - 力扣(LeetCode) (opens new window)
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
//base
if (root == null) return null;
if (root == p || root == q) return root;
TreeNode left = lowestCommonAncestor(root.left,p,q);
TreeNode right = lowestCommonAncestor(root.right,p,q);
//当 left 和 right 同时为空 :说明 root 的左 / 右子树中都不包含 p,q ,返回 null ;
if (left == null && right == null) {
return null;
}
//p,q 都不在 root 的左子树中,直接返回 right
//1)p,q 其中一个在 root 的 右子树 中,此时 right 指向 p(假设为 p );
//2)p,q 两节点都在 root 的 右子树 中,此时的 right 指向 最近公共祖先节点 ;
if (left == null) return right;
if (right == null) return left;
//当 left 和 right 同时不为空 :说明 p,q 分列在 root 的 异侧 (分别在 左 / 右子树),因此 root 为最近公共祖先,返回 root ;
return root;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 226. 翻转二叉树 - 力扣(LeetCode) (opens new window)
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) return null;
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
invertTree(root.left);
invertTree(root.right);
return root;
}
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) return null;
invertTree(root.left);
invertTree(root.right);
// 交换在递归之后
TreeNode temp = root.left;
root.left = root.right;
root.right = temp;
return root;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
BFS层序遍历
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) return null;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while(!queue.isEmpty()) {
TreeNode node = queue.poll();
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
return root;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
DFS栈模拟
class Solution {
public TreeNode invertTree(TreeNode root) {
if (root == null) return null;
Deque<TreeNode> stack = new LinkedList<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
// 交换左右子树
TreeNode temp = node.left;
node.left = node.right;
node.right = temp;
// 右、左子节点入栈
if (node.right != null) stack.push(node.right);
if (node.left != null) stack.push(node.left);
}
return root;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 求和等
# 124. 二叉树中的最大路径和 - 力扣(LeetCode) (opens new window)
class Solution {
private int res = Integer.MIN_VALUE;
public int maxPathSum(TreeNode root) {
maxGain(root);
return res;
}
private int maxGain(TreeNode node) {
if (node == null) return 0;
int left = Math.max(maxGain(node.left), 0); // 左贡献
int right = Math.max(maxGain(node.right), 0); // 右贡献
res = Math.max(res, node.val + left + right); // 更新全局
return node.val + Math.max(left, right); // 返回单侧贡献
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# BFS&DFS
# 199. 二叉树的右视图 - 力扣(LeetCode) (opens new window)
广度优先搜索(BFS):层序遍历,取每层最后一个节点
class Solution {
public List<Integer> rightSideView(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) return res;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
for (int i = 0; i < size; i++) {
TreeNode node = queue.poll();
// 记录当前层最后一个节点
if (i == size - 1) res.add(node.val);
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
}
return res;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
深度优先搜索(DFS):优先遍历右子树,记录每层首次访问的节点(即最右侧节点)
class Solution {
private List<Integer> res = new ArrayList<>();
public List<Integer> rightSideView(TreeNode root) {
dfs(root, 0);
return res;
}
private void dfs(TreeNode node, int depth) {
if (node == null) return;
// *******当前层首次访问的节点******
if (depth == res.size()) res.add(node.val);
// 需求右视图,先递归右子树
dfs(node.right, depth + 1);
dfs(node.left, depth + 1);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 129. 求根节点到叶节点数字之和 - 力扣(LeetCode) (opens new window)
dfs
class Solution {
public int sumNumbers(TreeNode root) {
return dfs(root, 0);
}
private int dfs(TreeNode node, int currentSum) {
if (node == null) return 0;
currentSum = currentSum * 10 + node.val;
if (node.left == null && node.right == null) { // 叶子节点
return currentSum;
}
return dfs(node.left, currentSum) + dfs(node.right, currentSum);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bfs
class Solution {
public int sumNumbers(TreeNode root) {
if (root == null) return 0;
Queue<TreeNode> nodeQueue = new LinkedList<>();
Queue<Integer> sumQueue = new LinkedList<>();
nodeQueue.offer(root);
sumQueue.offer(0);
int totalSum = 0;
while (!nodeQueue.isEmpty()) {
TreeNode node = nodeQueue.poll();
int currentSum = sumQueue.poll() * 10 + node.val;
if (node.left == null && node.right == null) {
totalSum += currentSum;
}
if (node.left != null) {
nodeQueue.offer(node.left);
sumQueue.offer(currentSum);
}
if (node.right != null) {
nodeQueue.offer(node.right);
sumQueue.offer(currentSum);
}
}
return totalSum;
}
}
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
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
# 101. 对称二叉树 - 力扣(LeetCode) (opens new window)
迭代
class Solution {
public boolean isSymmetric(TreeNode root) {
if (root == null) {
return true;
}
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root.left);
queue.offer(root.right);
while (!queue.isEmpty()) {
TreeNode leftNode = queue.poll();
TreeNode rightNode = queue.poll();
// 均空则继续
if (leftNode == null && rightNode == null) continue;
// 一空一非空或值不等
if (leftNode == null || rightNode == null || leftNode.val != rightNode.val) {
return false;
}
// 注意入队的顺序,对称性
queue.offer(leftNode.left);
queue.offer(rightNode.right);
queue.offer(leftNode.right);
queue.offer(rightNode.left);
}
return true;
}
}
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
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
递归
class Solution {
public boolean isSymmetric(TreeNode root) {
if (root == null) {
return true;
}
return check(root.left, root.right);
}
private boolean check(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 check(p.left, q.right) && check(p.right, q.left);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
# 104. 二叉树的最大深度 - 力扣(LeetCode) (opens new window)
递归
class Solution {
public int maxDepth(TreeNode root) {
if (root == null) return 0;
int leftDepth = maxDepth(root.left);
int rightDepth = maxDepth(root.right);
return Math.max(leftDepth, rightDepth) + 1;
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
bfs
class Solution {
public int maxDepth(TreeNode root) {
if (root == null) return 0;
Queue<TreeNode> queue = new LinkedList<>();
queue.offer(root);
int depth = 0;
while (!queue.isEmpty()) {
int levelSize = queue.size();
for (int i = 0; i < levelSize; i++) {
TreeNode node = queue.poll();
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
}
depth++;
}
return depth;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 662. 二叉树最大宽度 - 力扣(LeetCode) (opens new window)
BFS层序遍历(推荐)
class Solution {
public int widthOfBinaryTree(TreeNode root) {
if (root == null) return 0;
Queue<Pair<TreeNode, Integer>> queue = new LinkedList<>();
queue.offer(new Pair<>(root, 1));
int maxWidth = 0;
while (!queue.isEmpty()) {
int size = queue.size();
// 当前层首节点编号
int firstIndex = queue.peek().getValue();
int lastIndex = firstIndex;
for (int i = 0; i < size; i++) {
Pair<TreeNode, Integer> pair = queue.poll();
TreeNode node = pair.getKey();
// 更新尾节点编号
lastIndex = pair.getValue();
if (node.left != null) {
queue.offer(new Pair<>(node.left, 2 * lastIndex));
}
if (node.right != null) {
queue.offer(new Pair<>(node.right, 2 * lastIndex + 1));
}
}
// 每层的宽度即为该层最大编号 - 最小编号 + 1。此方法避免显式存储空节点,仅通过非空节点的编号计算宽度
maxWidth = Math.max(maxWidth, lastIndex - firstIndex + 1);
}
return maxWidth;
}
}
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
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
dfs
class Solution {
private int maxWidth = 0;
// 存储每层最左节点编号
private List<Integer> leftMost = new ArrayList<>(); // 存储每层最左节点编号
public int widthOfBinaryTree(TreeNode root) {
dfs(root, 1, 0);
return maxWidth;
}
private void dfs(TreeNode node, int index, int depth) {
if (node == null) return;
// 首次到达新层级,记录最左节点编号
if (depth == leftMost.size()) {
leftMost.add(index);
}
maxWidth = Math.max(maxWidth, index - leftMost.get(depth) + 1);
dfs(node.left, 2 * index, depth + 1);
dfs(node.right, 2 * index + 1, depth + 1);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 110. 平衡二叉树 - 力扣(LeetCode) (opens new window)
方法 方向 遍历顺序 时间复杂度 优势/劣势 自顶向下 根节点→叶节点 前序遍历 O(n²) 直观,但重复计算子树高度,效率低 自底向上 叶节点→根节点 后序遍历 O(n) 无重复计算,提前终止不平衡子树 推荐方法:自底向上(后序遍历),避免重复计算,效率更优。
class Solution {
// 高度(Height):从当前节点到最远叶子的路径节点数(本题使用)
// 深度(Depth):从根节点到当前节点的路径节点数
public boolean isBalanced(TreeNode root) {
return dfs(root) != -1;
}
private int dfs(TreeNode root) {
if (root == null) return 0;
int leftHeight = dfs(root.left);
if (leftHeight == -1) return -1;
int rightHeight = dfs(root.right);
if (rightHeight == -1) return -1;
// 比较左右子树高度差,若>1则返回-1;否则返回当前树高度max(left, right) + 1
if (Math.abs(leftHeight - rightHeight) > 1) return -1;
// 当前节点高度 = 最深子树的高度 + 自身
return Math.max(leftHeight, rightHeight) + 1;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 543. 二叉树的直径 - 力扣(LeetCode) (opens new window)
class Solution {
// 记录最大路径节点数(直径+1)
private int maxDiameter = 0;
public int diameterOfBinaryTree(TreeNode root) {
maxDepth(root);
// 路径长度 = 节点数 - 1
return maxDiameter - 1;
}
private int maxDepth(TreeNode node) {
if (node == null) return 0;
// 左子树深度
int leftDepth = maxDepth(node.left);
int rightDepth = maxDepth(node.right);
// 更新全局最大值:当前节点为转折点的路径节点数
maxDiameter = Math.max(maxDiameter, leftDepth + rightDepth + 1);
// 返回当前子树的深度
return Math.max(leftDepth, rightDepth) + 1;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 98. 验证二叉搜索树 - 力扣(LeetCode) (opens new window)
class Solution {
public boolean isValidBST(TreeNode root) {
// 调用递归方法,初始范围是 (-infinity, infinity)
/**
如果我们使用一个固定的值(例如 Integer.MIN_VALUE 或 Integer.MAX_VALUE),
可能会限制树的值的范围,导致错误判断。
因此,使用 Long 类型的最小值和最大值可以处理所有可能的节点值,避免溢出和边界问题
*/
return validate(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
private boolean validate(TreeNode node, long minVal, long maxVal) {
if (node == null) return true;
// 当前节点值必须在 (low, high) 范围内
if (node.val <= minVal || node.val >= maxVal) return false;
// 递归检查左右子树
// 对于左子树,右边界是当前节点的值
// 对于右子树,左边界是当前节点的值
return validate(node.left, minVal, node.val) && validate(node.right, node.val, maxVal);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
中序遍历递归法
class Solution {
private TreeNode prev = null; // 保存前驱节点
public boolean isValidBST(TreeNode root) {
if (root == null) return true;
if (!isValidBST(root.left)) return false;
// 检查当前节点是否 > 前驱节点
if (prev != null && root.val <= prev.val) return false;
prev = root;
return isValidBST(root.right);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
中序遍历迭代栈法
class Solution {
private TreeNode prev = null; // 保存前驱节点
public boolean isValidBST(TreeNode root) {
Deque<TreeNode> stack = new LinkedList<>();
TreeNode prev = null; // 前驱节点指针
TreeNode cur = root;
while (cur != null || !stack.isEmpty()) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
cur = stack.pop();
// 检查是否严格递增
if (prev != null && cur.val <= prev.val) {
return false;
}
// 更新前驱节点
prev = cur;
// 转向右子树
cur = cur.right;
}
return true;
}
}
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 112. 路径总和 - 力扣(LeetCode) (opens new window)
bfs
class Solution {
public boolean hasPathSum(TreeNode root, int targetSum) {
if (root == null) return false;
Queue<Pair<TreeNode, Integer>> queue = new LinkedList<>();
queue.offer(new Pair<>(root, root.val));
while (!queue.isEmpty()) {
Pair<TreeNode, Integer> pair = queue.poll();
TreeNode node = pair.getKey();
int currSum = pair.getValue();
if (node.left == null && node.right == null && currSum == targetSum) {
return true;
}
if (node.left != null) {
queue.offer(new Pair<>(node.left, currSum + node.left.val));
}
if (node.right != null) {
queue.offer(new Pair<>(node.right, currSum + node.right.val));
}
}
return false;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
递归
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);
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 113. 路径总和 II - 力扣(LeetCode) (opens new window)
dfs+回溯
class Solution {
private List<List<Integer>> result = new ArrayList<>();
private List<Integer> path = new ArrayList<>();
public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
dfs(root, targetSum);
return result;
}
private void dfs(TreeNode node, int remain) {
if (node == null) return;
// 1. 添加当前节点值,更新剩余目标
path.add(node.val);
remain -= node.val;
// 2. 到达叶子节点且目标和为0
if (node.left == null && node.right == null && remain == 0) {
// 深拷贝当前路径
result.add(new ArrayList<>(path));
}
// 3. 递归遍历左右子树
dfs(node.left, remain);
dfs(node.right, remain);
// 4. 回溯:移除当前节点
path.remove(path.size() - 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
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
编辑 (opens new window)
上次更新: 2025/07/25, 12:08:10