题解 | #二叉树中是否存在节点和为指定值的路径#

二叉树中是否存在节点和为指定值的路径

http://www.nowcoder.com/practice/508378c0823c423baa723ce448cbfd0c

此题解法可借鉴:二叉树根节点到叶子节点和为指定值的路径 https://blog.nowcoder.net/n/3ca862f49e6c409cb111db77c12932e8

算法思想一:递归

解题思路:

采用递归遍历二叉树的路径节点,同时计算二叉树路径节点的数字之和,当到达叶子节点且路径的数字之和等于 sum 则说明二叉树中存在节点和为指定值的路径
算法步骤:
1、特殊情况:当二叉树为空,则返回 false
2、遍历根节点的左右子树,记录根节点的数字之和 res
当节点的左右子树均为空,且 res == sum,则返回 true
3、递归 该节点的左右子树,做上述计算

代码展示:

Python版本
class Solution:
    def hasPathSum(self , root , sum ):
        # write code here
        def preOrder(root, res):
            if not root:
                return False
            # 计算节点数字之和
            res += root.val
            if not root.left and not root.right and res == sum:
                return True
            # 递归左右子树
            return preOrder(root.left, res)&nbs***bsp;preOrder(root.right, res)
        return False if not root else preOrder(root, 0)

复杂度分析:

时间复杂度 O(N) : N 为二叉树的节点数,最差的情况递归所有节点。
空间复杂度 O(1) : 常数级变量空间

算法思想二:深度优先遍历+回溯

解题思路:

1、首先,深度优点遍历来说,先写上一个回溯 if (curNode == null) { return false; },这表示递归至最深层开始回溯,至于为什么 return false 后面再讲
2、每次进入函数时,将 sum 减去当前节点的权重(curNode.val),当 sum 减到零时,说明目标路径存在,另外我们的目标是到叶子节点停止,叶子节点的条件是 curNode.left == null && curNode.right == null,所以说当 if (curNode.left == null && curNode.right == null && target == 0) ,我们返回 true 表示找到目标路径
3、深度遍历的分支:对于当前节点 curNode 有两个分支,这两个分支都有可能成为目标路径,所以深度优先遍历的写法为 return dfs(curNode.left, target) || dfs(curNode.right, target);
4、现在来谈谈为什么回溯时需要返回 false,因为当 curNode 为叶子节点时,并且 sum == 0 时,我们已经返回了 true,剩下的情况就是 curNode 不是叶子节点或者路径值不为 target,所应该返回 false
图解:

代码展示:

JAVA版本
public class Solution {
    /**
     * 
     * @param root TreeNode类 
     * @param sum int整型 
     * @return bool布尔型
     */
    public boolean hasPathSum (TreeNode root, int sum) {
        // write code here
        if (root == null) {
            return false;
        }
        // 深度优先遍历
        return dfs(root, sum);
    }
    
    private boolean dfs(TreeNode curNode, int target) {
        // 目标路径不存在,开始回溯
        if (curNode == null) {
            return false;
        }
        // 更新目标值
        target -= curNode.val;
        // 当当前节点为叶子节点并且目标路径存在时,返回 true
        if (curNode.left == null && curNode.right == null && target == 0) {
            return true;
        }
        // 对左右分支进行 dfs
        return dfs(curNode.left, target) || dfs(curNode.right, target);
    }
}

复杂度分析:

时间复杂度 O(N) : N 为二叉树的节点数,最差的情况递归所有节点。
空间复杂度 O(1) :不需要额外空间





全部评论
递归方法的空间复杂度是logn吧,函数调用栈的深度是logn
3 回复 分享
发布于 2022-02-24 20:59
代码和思路有点相似。
1 回复 分享
发布于 2021-11-18 00:36
很牛 你是懂o(1)的
1 回复 分享
发布于 2022-10-18 19:18 山东
空间复杂度不应该是每次递归的空间复杂度*递归深度吗?不应该是O(树的高度)吗?
点赞 回复 分享
发布于 2022-03-02 21:02
你确定是O(1)吗.
点赞 回复 分享
发布于 2022-05-06 15:44
空间复杂度O(1)还行
点赞 回复 分享
发布于 2023-02-14 13:35 湖北
第二个不也是递归吗
点赞 回复 分享
发布于 2023-07-21 16:58 陕西

相关推荐

手撕没做出来是不是一定挂
Chrispp3:不会,写出来也不一定过
点赞 评论 收藏
分享
11-15 17:19
湖南大学 Java
成果成果成果果:这是哪个公司的hr,这么离谱吗,我没见过用性别卡技术岗的,身边女性同学拿大厂offer的比比皆是
点赞 评论 收藏
分享
评论
30
6
分享
牛客网
牛客企业服务