返回
寻径问道,解开二叉树路径总和之谜
前端
2023-12-24 12:40:06
导言
在浩瀚的算法世界中,二叉树作为一种经典的数据结构,以其简洁高效的特性而备受推崇。而二叉树路径总和问题更是算法竞赛中的常客,考验着算法工程师们的基本功底。
问题定义
给定一棵二叉树的根节点 root
和一个整数 targetSum
,求出从根节点到叶节点的路径中,所有路径的和等于 targetSum
的路径条数。
递归算法
递归,作为算法设计中常用的技巧,在解决二叉树路径总和问题中也能大显身手。递归算法的思路如下:
- 从根节点开始,递归地求解其左右子树的路径总和。
- 对于每个子树,如果其路径总和等于
targetSum
,则路径条数加 1。 - 返回当前根节点的路径条数。
public int pathSum(TreeNode root, int targetSum) {
if (root == null) {
return 0;
}
int res = pathSumFrom(root, targetSum);
res += pathSum(root.left, targetSum);
res += pathSum(root.right, targetSum);
return res;
}
private int pathSumFrom(TreeNode root, int targetSum) {
if (root == null) {
return 0;
}
int res = 0;
if (root.val == targetSum) {
res++;
}
res += pathSumFrom(root.left, targetSum - root.val);
res += pathSumFrom(root.right, targetSum - root.val);
return res;
}
深度优先搜索
深度优先搜索(DFS)算法也是解决二叉树路径总和问题的有效方法。DFS 的思路如下:
- 从根节点开始,将其压入栈中。
- 循环执行以下步骤,直到栈为空:
- 弹出栈顶元素
node
。 - 计算从根节点到
node
的路径总和pathSum
。 - 如果
pathSum
等于targetSum
,则路径条数加 1。 - 将
node
的左右子树压入栈中。
- 弹出栈顶元素
public int pathSum(TreeNode root, int targetSum) {
if (root == null) {
return 0;
}
int res = 0;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
int pathSum = node.val;
if (pathSum == targetSum) {
res++;
}
if (node.left != null) {
node.left.val += node.val;
stack.push(node.left);
}
if (node.right != null) {
node.right.val += node.val;
stack.push(node.right);
}
}
return res;
}
实例与分析
我们以一棵简单二叉树为例,其节点值分别为 [10, 5, -3, 3, 2, null, 11, 3, -2, null, 1]:
10
/ \
5 -3
/ \ / \
3 2 -2 1
\ \
3 -2
\
1
递归算法
从根节点 10 开始递归:
- 左子树的路径总和:3 + 2 + 3 + 1 = 9
- 右子树的路径总和:-2 + 1 = -1
- 当前根节点的路径总和:10
- 路径条数:0
深度优先搜索算法
从根节点 10 开始遍历:
- 从栈中弹出根节点 10,路径总和:10
- 路径条数:1
- 将左右子树压入栈中
- 从栈中弹出左子树节点 5,路径总和:15
- 路径条数:1
- 将左右子树压入栈中
- ...
通过继续遍历,我们可以得到最终路径条数为 3。
总结
二叉树路径总和算法的求解涉及递归和深度优先搜索两种方法。这两种方法各有优缺点,递归算法实现简单直观,而深度优先搜索算法效率更高。在实际应用中,开发者可以根据具体情况选择最适合的方法。
掌握了二叉树路径总和算法,不仅可以加深我们对二叉树数据结构的理解,还可以为解决更复杂的数据结构问题奠定基础。算法学习的道路漫漫其修远,但只要我们不断探索和实践,终能登堂入室,领略算法之美。