在问 · 算法题解

112. 路径总和

简单二叉树递归深度优先搜索力扣原题 ↗

题目描述

输入二叉树的根节点 root 和一个整数 targetSum。

考虑所有从根出发、一直走到某个叶子节点的路径。叶子节点指没有任何孩子的节点。只要有一条这样的路径,其节点值之和恰好为 targetSum,就返回 true;一条都没有就返回 false。

空树里不存在任何路径,返回 false。树用层序数组表示,null 代表空位。

示例 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,都不是 5。

示例 3
输入:root = [], targetSum = 0
输出:false

解释:树为空,没有路径可选。

数据范围

  • 节点总数在 [0, 5000] 之间。
  • -1000 <= Node.val <= 1000
  • -1000 <= targetSum <= 1000

解题思路:递归深度优先搜索

每往下走一个节点,就把它的值从 targetSum 里减掉,问题变成“子树里是否有一条路径和等于剩下的数”。走到叶子时,剩余值恰好为 0 就说明找到了。左子树找到就直接返回 True,借助 or 的短路不再搜索右子树。

为什么正确

调用 hasPathSum(node, t) 时,t 等于原 targetSum 减去从根到 node 父节点的路径和。

复杂度分析

时间 O(n),空间 O(h),h 为树高。

易错点

只能在叶子处判断剩余值是否为 0。如果在空节点处判断,一个只有一侧孩子的节点会把“空的那一侧”误当作路径终点。另外节点值可能为负,不能在剩余值小于 0 时提前剪枝。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if not root:
            return False
        targetSum -= root.val
        if not root.left and not root.right:
            return targetSum == 0
        return self.hasPathSum(root.left, targetSum) or self.hasPathSum(root.right, targetSum)

载入编辑器,自己跑一遍 →

其他解法

递归把剩余目标值传给子树,代码最短;广度优先搜索把路径和和节点一起入队,空间随层宽变化。

解法 2:广度优先搜索 时间 O(n),空间 O(w)

队列里同时保存节点和从根到它的路径和。弹出节点时,如果它是叶子并且路径和等于 targetSum,就返回 true。否则把子节点连同累加后的路径和入队。

没有递归,深链树不会栈溢出。需要额外保存每个待处理节点的路径和,代码比递归长。

from collections import deque

class Solution:
    def hasPathSum(self, root, targetSum):
        if not root:
            return False
        queue = deque([(root, root.val)])
        while queue:
            node, s = queue.popleft()
            if not node.left and not node.right and s == targetSum:
                return True
            if node.left:
                queue.append((node.left, s + node.left.val))
            if node.right:
                queue.append((node.right, s + node.right.val))
        return False

二叉树 专题的其他题目

查看 二叉树 全部题目 →