LeetCode:112 路径总和

135 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第13天,点击查看活动详情

题目

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

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

示例 1:

img

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

示例 2:

img

输入: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

解题

解题一:递归

思路

从根节点到叶子节点的值是否满足目标整数 targetSum,我们可以将问题拆分为

  1. 左子树是否存在满足目标整数 targetSum - 根节点值的路径
  2. 右子树是否存在满足目标整数 targetSum - 根节点值的路径
  3. 只要前面两个节点其中一个满足,则总体满足
  4. 再进一步,我们将根节点泛化为当前节点,这样通过递归的方式就可以判断是否存在满足条件的路径

代码

/**
 * Definition for a binary tree node.
 */
public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode() {
    }

    TreeNode(int val) {
        this.val = val;
    }

    TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

class Solution {

    public boolean hasPathSum(TreeNode root, int targetSum) {
        if (root == null) {
            return false;
        }
        if (root.left == null && root.right == null) {
            return root.val == targetSum;
        }
        return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
    }
}

总结

性能分析

  • 执行耗时:0 ms,击败了 100.00% 的 Java 用户
  • 内存消耗:41.6 MB,击败了 5.06% 的 Java 用户

解题二:广度优先搜索

思维

使用两个队列,一个队列 nodeStack 存放节点,一个 resultStack 存放跟节点到 nodeStack 对应节点的距离

  1. 将根节点存入 nodeStack,根节点的值存入 resultStack
  2. 取出 nodeStack 和 resultStack 的值
    1. 如果取出的节点不是叶子节点,则继续进行存放 nodeStack 和 resultStack 操作
    2. 如果取出的节点是叶子节点,判断和目标整数 targetSum 是否相等

代码

import java.util.Stack;

/**
 * Definition for a binary tree node.
 */
public class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode() {
    }

    TreeNode(int val) {
        this.val = val;
    }

    TreeNode(int val, TreeNode left, TreeNode right) {
        this.val = val;
        this.left = left;
        this.right = right;
    }
}

class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum) {
        if (root == null) {
            return false;
        }
        Stack<TreeNode> nodeStack = new Stack<>();
        Stack<Integer> resultStack = new Stack<>();
        nodeStack.push(root);
        resultStack.push(root.val);
        while (!nodeStack.isEmpty()) {
            TreeNode pop = nodeStack.pop();
            Integer tempResult = resultStack.pop();
            // 计算孩子节点的值
            if (pop.left != null) {
                nodeStack.push(pop.left);
                resultStack.push(tempResult + pop.left.val);
            }
            if (pop.right != null) {
                nodeStack.push(pop.right);
                resultStack.push(tempResult + pop.right.val);
            }
            if (pop.left == null && pop.right == null) {
                // 叶子节点,判断是否满足条件
                resultStack.push(tempResult);
            }
        }
        return resultStack.contains(targetSum);
    }
}

总结

性能分析

  • 执行耗时:2 ms,击败了 6.97% 的 Java 用户
  • 内存消耗:41.3 MB,击败了 46.27% 的 Java 用户