【力扣题解】P112-路径总和-Java题解

花无缺

‍博客主页:@花无缺
欢迎 点赞 收藏⭐ 留言 加关注✅!
本文由 花无缺 原创

收录于专栏 【力扣题解】


文章目录

  • 【力扣题解】P112-路径总和-Java题解
    • 题目描述
    • 题解
    • 总结


【力扣题解】P112-路径总和-Java题解

P112. 路径总和

题目描述

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

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

示例 1:

【力扣题解】P112-路径总和-Java题解_第1张图片

输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。

示例 2:

【力扣题解】P112-路径总和-Java题解_第2张图片

输入:root = [1,2,3], targetSum = 5
输出:false
解释:树中存在两条根节点到叶子节点的路径:
(1 --> 2): 和为 3
(1 --> 3): 和为 4
不存在 sum = 5 的根节点到叶子节点的路径。

示例 3:

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

提示:

  • 树中节点的数目在范围 [0, 5000]
  • -1000 <= Node.val <= 1000
  • -1000 <= targetSum <= 1000

题解

广度优先搜索递归(详细代码)

public boolean hasPathSum(TreeNode root, int targetSum) {
    // 空树, 返回 false
    if (root == null) {
        return false;
    }
    return dfs(root, targetSum - root.val);
}
public boolean dfs(TreeNode node, int count) {
    // 当前节点是叶子节点并且 count == 0, 说明找到了题目要求的路径
    // 返回 true, 递归终止
    if (node.left == null && node.right == null && count == 0) {
        return true;
    }
    // count != 0, 不是题目要求的路径, 直接返回 false, 递归终止
    if (node.left == null && node.right == null) {
        return false;
    }
    // 递归左子树
    if (node.left != null) {
        // 处理左子节点的 count 值
        count = count - node.left.val;
        // 如果左子节点满足了题目要求的路径, 直接返回 true
        if (dfs(node.left, count)) {
            return true;
        }
        // 回溯, 将 count 恢复之前的值
        count = count + node.left.val;
    }
    // 递归右子树
    if (node.right != null) {
        // 处理右子节点的 count 值
        count = count - node.right.val;
        // 如果右子节点满足了题目要求的路径, 直接返回 true
        if (dfs(node.right, count)) {
            return true;
        }
        // 回溯, 将 count 恢复之前的值
        count = count + node.right.val;
    }
    // 树的所有路径都不满足题目条件, 返回 false
    return false;
}

广度优先搜索递归(简化代码)

public boolean hasPathSum(TreeNode root, int targetSum) {
    // 空树, 返回 false
    if (root == null) {
        return false;
    }
    // 如果当前节点是叶子节点并且 targetSum 等于当前节点值
    // 说明找到了题目要求的路径
    if (root.left == null && root.right == null && targetSum == root.val) {
        return true;
    }
    // 没有找到路径, 继续递归遍历左子树和右子树
    // 此时要将 targetSum 减去当前节点值, 表示遍历进入了当前节点的下一节点
    // 所以要把当前节点值减去
    // 当遍历到符合条件的叶子节点时, targetSum 就已经递减到和叶子节点值相等了
    // 如果左右子树都不符合, 那么返回时(回溯), targetSum 的大小并没有改变
    return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
}

时间复杂度:O(n),要遍历树的所有节点一次,树的节点数为 n。

深度优先搜索

public boolean hasPathSum(TreeNode root, int targetSum) {
    if (root == null) {
        return false;
    }
    Queue<TreeNode> nodeQueue = new LinkedList<>();
    Queue<Integer> valQueue = new LinkedList<>();
    nodeQueue.offer(root);
    valQueue.offer(root.val);
    while (!nodeQueue.isEmpty()) {
        TreeNode node = nodeQueue.poll();
        int val = valQueue.poll();
        // 当前节点是叶子节点
        if (node.left == null && node.right == null) {
            // 当前路径和等于 targetSum, 返回 true
            if (val == targetSum) {
                return true;
            //     否则继续遍历
            } else {
                continue;
            }
        }
        // 遍历左子树
        if (node.left != null) {
            // 左子节点进队
            nodeQueue.offer(node.left);
            // 将左子节点的值加入路径和中
            valQueue.offer(node.left.val + val);
        }
        // 遍历右子树
        if (node.right != null) {
            // 右子节点进队
            nodeQueue.offer(node.right);
            // 将右子节点的值加入路径和中
            valQueue.offer(node.right.val + val);
        }
    }
    return false;
}

时间复杂度:O(n),要遍历树的所有节点一次,树的节点数为 n。

总结

这个题要求我们找到一条路径的和等于指定值 targetSum,那么我们肯定要先遍历这棵树,遍历这棵树的过程中同时判断当前路径的节点总和是否等于 targetSum,那么我们就要每经过一个节点将当前路径的节点值累加,这样的查找是很麻烦的,我们可以换个思路,当找到符合条件的叶子节点时,路径累加的和刚好等于 targetSum,那么我们可以从第一个节点开始依次将 targetSum 将去当前节点值,当找到符合条件的路径的最后一个节点(叶子结点)时,targetSum 刚好等于 0。根据这个我们可以写出深度优先搜索的递归代码。

这个题我们也可以使用广度优先搜索的方法来做,但是要借助两个队列,一个队列用来对树进行层次遍历,存储节点,一个队列用来存储路径和,我们在遍历树的过程中,每遍历一个节点就将节点值累加并加入节点值队列 valQueue,这个节点值刚好对应当前节点之前的路径和,所以每次将当前节点和节点值出队,就可以判断路径和是否等于 targetSum,从而达到题目效果。

作者:花无缺(huawuque404.com)


欢迎关注我的博客:花无缺-每一个不曾起舞的日子都是对生命的辜负~
一起进步-刷题专栏:【力扣题解】
往期精彩好文:
【CSS选择器全解指南】
【HTML万字详解】
你们的点赞 收藏⭐ 留言 关注✅
是我持续创作,输出优质内容的最大动力!
谢谢!

你可能感兴趣的:(力扣题解,leetcode,java,算法,数据结构)