路径总和III

last modify

问题简述

给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。

路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。

437. 路径总和 III - 力扣(LeetCode)

思路1:先序遍历

  • 先序遍历每个节点,每个节点再先序遍历找目标值;

Python
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def pathSum(self, root: TreeNode, targetSum: int) -> int:  # noqa
        """"""
        if root is None:
            return 0

        def dfs(x, rest):
            if not x:
                return 0

            ans = 0 if x.val != rest else 1  # 如果相等说明,从头结点开始到该节点可以形成一条路径

            # 继续遍历左右子树
            rest -= x.val
            ans += dfs(x.left, rest)
            ans += dfs(x.right, rest)
            rest += x.val  # 回溯
            return ans

        # dfs 是一个先序遍历
        ret = dfs(root, targetSum)
        # pathSum 本身也是一个先序遍历,相当于对每个点都做一次 dfs
        ret += self.pathSum(root.left, targetSum)
        ret += self.pathSum(root.right, targetSum)

        return ret

思路2:先序遍历+前缀和(最优)

【宫水三叶】一题双解 :「DFS」&「前缀和」 - 路径总和 III - 力扣(LeetCode)

Python
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def pathSum(self, root: TreeNode, targetSum: int) -> int:
        from collections import defaultdict
        self.prefix = defaultdict(int)  # 保存前缀和
        self.prefix[0] = 1
        self.targetSum = targetSum

        def dfs(x, preSum):
            if not x: return 0

            ret = 0
            preSum += x.val
            ret += self.prefix[preSum - targetSum]

            self.prefix[preSum] += 1
            ret += dfs(x.left, preSum)
            ret += dfs(x.right, preSum)
            self.prefix[preSum] -= 1

            return ret

        return dfs(root, 0)

思路3:后序遍历(推荐)

Python
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right

class Solution:
    def pathSum(self, root: TreeNode, targetSum: int) -> int:
        
        from dataclasses import dataclass

        @dataclass
        class Info:
            cnt: int  # 题目要求的路径数目
            dp: list  # 保存所有可能的路径和

        def dfs(x):
            if not x:
                return Info(0, [])
            
            l, r = dfs(x.left), dfs(x.right)

            x_cnt = l.cnt + r.cnt
            x_dp = [x.val]
            if x.val == targetSum:
                x_cnt += 1
            for t in l.dp:
                x_dp.append(t + x.val)
                if t + x.val == targetSum:
                    x_cnt += 1
            for t in r.dp:
                x_dp.append(t + x.val)
                if t + x.val == targetSum:
                    x_cnt += 1

            return Info(x_cnt, x_dp)
        
        return dfs(root).cnt

Last updated