leetcode树之路径总和

112、路径总和

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。

叶子节点 是指没有子节点的节点。

示例1:

输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true

示例2:

输入:root = [1,2,3], targetSum = 5
输出:false

示例3:

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

思路

这道题比较直观的想法是用迭代,找到目标值,这里要注意路径的终止条件为叶子结点。

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

广度优先遍历

class Solution:
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if not root: return False
        # 这里用两个栈来映射当前结点以及当前结点路径的总和
        queue = [root]
        # 这里也可以用hash来存储,不过由于这两个queue是同步操作,所以值是一一对应的
        queue_val = [root.val]
        while queue:
            cur = queue.pop(0)
            val = queue_val.pop(0)
            # 当前结点如果没有左子节点和右子结点时,判断是否满足条件
            # 如果满足条件,返回即可,如果不满足,继续遍历
            if not cur.left and not cur.right:
                if val == sum: return True
                continue
            if cur.left:
                queue.append(cur.left)
                queue_val.append(cur.left.val + val)
            if cur.right:
                queue.append(cur.right)
                queue_val.append(cur.right.val + val)
        return False
113、路径总和2

给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。

叶子节点 是指没有子节点的节点。

示例1:

输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:[[5,4,11,2],[5,8,4,5]]

示例2:

输入:root = [1,2,3], targetSum = 5
输出:[]

示例3:

输入:root = [1,2], targetSum = 0
输出:[]

思路

这道题和上面的比较相似,只不过这里需要返回所有的路径。

class Solution:
    def pathSum(self, root: Optional[TreeNode], targetSum: int) -> List[List[int]]:
        if not root: return []
        # 如果没有子节点,并且结点值等于给定的值,返回结点值
        if not root.left and not root.right and root.val == targetSum:
            return [[root.val]]
        # 由于方法都是返回的数组,直接拼接即可,然后在每个里层元素添加头结点
        ans = self.pathSum(root.left, targetSum - root.val) + self.pathSum(root.right, targetSum - root.val)
        [item.insert(0, root.val)for item in ans]
        return ans
124、二叉树中的最大路径和

路径 被定义为一条从树中任意节点出发,沿父节点-子节点连接,达到任意节点的序列。同一个节点在一条路径序列中 至多出现一次 。该路径 至少包含一个 节点,且不一定经过根节点。

路径和 是路径中各节点值的总和。

给你一个二叉树的根节点 root ,返回其 最大路径和 。

示例1:

输入:root = [1,2,3]
输出:6
解释:最优路径是 2 -> 1 -> 3 ,路径和为 2 + 1 + 3 = 6

示例2:

输入:root = [-10,9,20,null,null,15,7]
输出:42
解释:最优路径是 15 -> 20 -> 7 ,路径和为 15 + 20 + 7 = 42

思路:

对于当前节点来说,当前节点的路径和应该是当前节点值+左子树路径 + 右子树路径,那么最大值应该是需要判断左右子树的路径和大于零才加到路径上。那么对于子树的最大路径应该是取子节点以及其左右子树的最大值。

class Solution:
    def maxPathSum(self, root: Optional[TreeNode]) -> int:
        self.ans = float('-inf')
        def dfs(root):
            if not root: return 0
            # 获取左右子树的值
            left = max(dfs(root.left), 0)
            right = max(dfs(root.right), 0)
            # 当前节点的最大路径和应该是当前节点值 + 左子树 + 右子树(大于0)
            # 并更新结果值
            cur = root.val + left + right
            self.ans = max(self.ans, cur)
            # 而当前节点的返回值应该是当前值 + 左右子树(大于0)的值
            return root.val + max(left, right)
        dfs(root)
        return self.ans
437、路径总和3

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

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

示例1:

输入:root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
输出:3

示例2:

输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:3

思路

class Solution:
    def pathSum(self, root: TreeNode, targetSum: int) -> int:
        def dfs(root, targetSum):
            if not root: return 0
            sum = 0
            if root.val == targetSum:
                sum += 1
            sum += dfs(root.left, targetSum - root.val) + dfs(root.right, targetSum - root.val)
            return sum
        if not root: return 0
        return dfs(root, targetSum) + self.pathSum(root.left, targetSum) + self.pathSum(root.right, targetSum)

前缀和:

如果在某条路径上,发现该路径的和减去targetSum之前出现过,那么就说明在这条路径上肯定有子路径到该结点的和为targetSum。

class Solution:
    def pathSum(self, root: TreeNode, targetSum: int) -> int:
        prefixSum = collections.defaultdict(int)
        prefixSum[0] = 1
        def dfs(root, cur):
            if not root: return 0
            sum = 0
            cur += root.val
            # 这里先看之前有没有满足的值
            sum += prefixSum[cur - targetSum]
            # 由于cur是先于cur-targetSum的,所以这里设置1,那么后面的cur-targetSum就可能取到该值
            prefixSum[cur] += 1
            sum += dfs(root.left, cur) + dfs(root.right, cur)
            # 处理完成之后,将这里进行减一操作,避免重复计算
            prefixSum[cur] -= 1
            return sum

        return dfs(root, 0)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

溪语流沙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值