路径总和III
问题简述
给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。
路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。思路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:先序遍历+前缀和(最优)
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).cntLast updated