[路飞]_前端算法第五十一弹-112. 路径总和

249 阅读3分钟

给你二叉树的根节点 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
解释:树中存在两条根节点到叶子节点的路径:
(1 --> 2): 和为 3
(1 --> 3): 和为 4
不存在 sum = 5 的根节点到叶子节点的路径。

示例 3:

输入:root = [], targetSum = 0
输出:false
解释:由于树是空的,所以不存在根节点到叶子节点的路径。

广度优先

首先我们可以想到使用广度优先搜索的方式,记录从根节点到当前节点的路径和,以防止重复计算。

这样我们使用两个队列,分别存储将要遍历的节点,以及根节点到这些节点的路径和即可。

var sumNumbers = function(root) {
if(!root) return false
    // 创建两个队列
    // 用来存储节点
    let nodeQue = []
    // 用来存储根节点到这个节点的总和
    let valQue = []

    // 先将根节点入队列
    nodeQue.unshift(root)
    valQue.unshift(root.val)

    while(nodeQue.length > 0){
        // 将队头元素取出来得到节点root和值temp
        let root = nodeQue.pop()
        let temp = valQue.pop()

        // 如果这个节点是叶子节点(没有左右孩子)
        if(!root.left && !root.right){
            // 如何符合要求返回true 并 退出函数
            if(temp === targetSum) return true
            // 不满足要求 下面的都不会满足,就进行下一轮循环了
        }
        // 有左孩子就进来
        if(root.left){
            // 左孩子进队列
            nodeQue.unshift(root.left)
            // 保存此时路径总和
            valQue.unshift(root.left.val + temp)
        }
        // 有右孩子就进来
        if(root.right){
            // 右孩子进队列
            nodeQue.unshift(root.right)
            // 保存此时路径总和
            valQue.unshift(root.right.val + temp)
        }
    }
    // 循环走完都没有返回true就说明没有符合要求的路径总和
    return false
};

深度优先

观察要求我们完成的函数,我们可以归纳出它的功能:询问是否存在从当前节点 root 到叶子节点的路径,满足其路径和为 sum

假定从根节点到当前节点的值之和为 val,我们可以将这个大问题转化为一个小问题:是否存在从当前节点的子节点到叶子的路径,满足其路径和为 sum - val

不难发现这满足递归的性质,若当前节点就是叶子节点,那么我们直接判断 sum 是否等于 val 即可(因为路径和已经确定,就是当前节点的值,我们只需要判断该路径和是否满足条件)。若当前节点不是叶子节点,我们只需要递归地询问它的子节点是否能满足条件即可。

var hasPathSum = function (root, sum) {
    if (!root) return false;
    if (!root.left && !root.right) return (root.val == sum)
    return hasPathSum(root.left, sum - root.val) || hasPathSum(root.right, sum - root.val)
};