0112.路径总和
难度:🟢 简单
标签:树
、深度优先搜索
、广度优先搜索
、二叉树
、递归
链接:112. 路径总和
题目描述
给你二叉树的根节点 root
和一个表示目标和的整数 targetSum
。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum
。如果存在,返回 true
;否则,返回 false
。
叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:存在路径 5->4->11->2 ,其节点值之和为 22 。
示例 2:
输入:root = [1,2,3], targetSum = 5
输出:false
解释:树中存在两条根节点到叶子节点的路径,它们的和分别是 3 和 4 。
示例 3:
输入:root = [1,2], targetSum = 0
输出:false
解题思路
核心思想
本题的核心思想是利用递归,通过 深度优先搜索(DFS) 遍历树的每一条“根到叶”的路径。在遍历的过程中,我们不断地从目标和 targetSum
中减去当前节点的值。如果当我们到达一个叶子节点时,剩余的目标和恰好等于这个叶子节点的值,那么就说明我们找到了一条符合条件的路径。
思路选择
递归是解决此问题最自然、最直观的方法。定义一个函数,该函数的功能是判断“在以当前节点为起点的子树中,是否存在一条到叶子节点的路径,其和等于传入的目标值”。
关键步骤
递归的终止条件 1 (空节点):如果当前节点为
null
,说明此路不通,直接返回false
。递归的终止条件 2 (叶子节点):如果当前节点是一个叶子节点(即左右子节点都为
null
),此时我们判断当前节点的值是否恰好等于我们期望的目标值targetSum
。如果是,说明从根节点到此叶子节点的路径和满足条件,返回true
。递归的递推关系:如果当前节点不是叶子节点,我们需要继续向下探索。我们将问题分解为在左子树和右子树中寻找路径的问题。
向左子树递归,新的目标和变为
targetSum - root.val
。向右子树递归,新的目标和也变为
targetSum - root.val
。只要左、右子树中任意一条路径满足条件,就说明整棵树存在满足条件的路径。因此,我们将两个递归调用的结果用“或”(
||
)连接起来。
代码实现
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @param {number} targetSum
* @return {boolean}
*/
var hasPathSum = function(root, targetSum) {
// 1. 如果节点为空,直接返回 false
if(root === null) {
return false;
}
// 2. 如果是叶子节点,判断其值是否等于剩余的目标和
if(root.left === null && root.right === null && root.val === targetSum) {
return true;
}
// 3. 递归地在左子树和右子树中寻找路径
// 新的目标和是当前目标和减去当前节点的值
return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
};
复杂度分析
时间复杂度:O(n) 其中 n 是树的节点总数。在最坏的情况下,我们需要访问树中的每一个节点一次。
空间复杂度:O(h) 其中 h 是树的高度。空间复杂度主要由递归调用栈的深度决定。在最坏的情况下(树退化为一条链),递归深度为 n,空间复杂度为 O(n);在最好的情况下(一个完全平衡的树),递归深度为 log(n),空间复杂度为 O(log n)。
相关题目
0113.路径总和 II (找出所有满足条件的路径)
0437.路径总和 III (路径不一定需要从根节点开始,也不需要在叶子节点结束)
总结
本题是检验二叉树递归遍历基本功的经典题目。通过将大问题(在整棵树中寻找路径)分解为小问题(在子树中寻找路径,并更新目标和),可以优雅地解决问题。理解递归的终止条件和递推关系是解题的关键。