二叉树根节点到叶子节点和为指定值的路径

775 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动

二叉树根节点到叶子节点和为指定值的路径

问题描述

给定一个节点数为 n 的二叉树和一个值 sum ,请找出所有的根节点到叶子节点的节点值之和等于的路径,如果没有则返回空。

例如: 给出如下的二叉树,sum = 22。

image-20211018102641490.png

返回:[ [5,4,11,2], [5,8,9] ]

分析问题

这道题比较简单,本质上就是搜索二叉树。对于二叉树的搜索,我们知道有深度优先搜索和广度优先搜索两种,所有这道题我们也可以有两种方式来求解。

深度优先搜索

找出所有的根节点到叶子节点的节点值之和等于的路径,我们可以枚举每一条根节点到叶子节点的路径,如果路径和恰好为目标和时,我们就找到了一条满足条件的路径。

class Solution:
    def pathSum(self, root, target):
        if not root:
            return []
        #存放所有的路径
        ret = list()
        #记录根节点到当前节点的路径和,防止重复计算
        path = list()

        def dfs(root, target):
            #将该节点对于的value加入path中
            path.append(root.val)

            target -= root.val
            #如果为叶子节点,并且路径和等于target,则把该路径加入res中
            if not root.left and not root.right and target == 0:
                ret.append(path[:])
            #如果左孩子不为空,继续去搜索
            if root.left:
               dfs(root.left, target)
            #如果右孩子不为空,继续去搜索
            if root.right:
               dfs(root.right, target)
            #将该节点弹出
            path.pop()

        dfs(root, target)
        return ret

广度优先搜索

我们也可以采用广度优先搜索的方式来求解。这里,我们使用一个哈希表来记录树中的每一个节点的父节点,再每一次找到一个满足条件的叶子节点时,我们就从该叶子节点出发,不断的向父节点迭代,即可还原出一条路径,使得从根节点到叶子节点的路径和等于目标值。

import collections
class Solution:
    def pathSum(self, root, target):
        #如果root为空,直接返回
        if not root:
            return []

        ret = []

        #用来保存父节点和子节点的关系
        parent = {}
        #根节点的父节点为None
        parent[root]=None

        #从该节点出发,一直寻找到根节点,还原出一条路径
        def getPath(node):
            tmp = []
            while node:
                tmp.append(node.val)
                node = parent[node]
            ret.append(tmp[::-1])

        #建立一个队列,保存遍历到哪个节点,初始时,把根节点加入
        node_que = collections.deque([root])
        #记录从根节点走到某个节点时,累加的距离为多少,初始时为0
        value_count_que = collections.deque([0])

        while node_que:
            #出队
            node = node_que.popleft()
            #将该节点的值进行累加
            rec = value_count_que.popleft() + node.val

            #如果是根节点,判断是否等于目标值,如果相等,则保存路径
            if not node.left and not node.right:
                if rec == target:
                    getPath(node)
            else:
                #如果左孩子存在,将节点加入node_que,将rec加入value_count_que
                if node.left:
                    parent[node.left] = node
                    node_que.append(node.left)
                    value_count_que.append(rec)
                #如果右孩子存在,将节点加入node_que,将rec加入value_count_que
                if node.right:
                    parent[node.right] = node
                    node_que.append(node.right)
                    value_count_que.append(rec)

        return ret