LeetCode 437.路径总和 III

122 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

题目:给定二叉树的根节点root,以及一个整数targetSum,求此二叉树中节点值之和等于targetSum的路径的数目。此路径不需要从根节点开始也不需要在叶子节点结束。

解题思路

本题和LeetCode 560那题很类似,可以先理解LeetCode 560这题再来看本题。

560那题一样,本题也可使用暴力解法,解题步骤为:

首先确定根节点,由此根节点向下遍历,每次遍历都累加路径之和,当路径之和等于targetSum时即该路径满足条件,直到遍历到叶子节点。

以上面的思路将二叉树中每个节点都这样遍历一遍,可得代码如下:

public int pathSum(TreeNode root, int targetSum) {
    if(root == null) return 0;
    int res = rootSum(root, targetSum);

    res += pathSum(root.left, targetSum);
    res += pathSum(root.right, targetSum);
    return res;
}

public int rootSum(TreeNode root, int targetSum){
    if(root == null) return 0;

    int res = 0;
    if(targetSum == root.val) res++;
    res += rootSum(root.left, targetSum-root.val);
    res += rootSum(root.right, targetSum-root.val);
    return res;
}

上述算法的时间复杂度为O(N2)O(N^2), 空间复杂度为O(N)O(N)

前缀和 + 哈希

实际上,在我们遍历一整颗树的时候,我们已经将重要信息保存下来了,这个重要信息就是前缀和,我们想象一下,对于一颗只有左子树的二叉树,如1-> 2-> 3,假设此时的target3,我们保留的前缀和树为1 -> 3 -> 6,当我们遍历到6的时候,此时树中存在前缀和为6-3=3的路径,则此时前缀和为3到前缀和为6的这条路径必定存在一条满足的路径。

表达的不清楚,这篇题解写的很好,可以参考: 对前缀和解法的一点解释 - 路径总和 III 代码如下:

public int pathSum2(TreeNode root, int targetSum) {
    if(root == null) return 0;
    HashMap<Integer, Integer> map = new HashMap<>();
    map.put(0, 1);
    return rootSum2(root, targetSum, 0, map);
}

public int rootSum2(TreeNode root, int targetSum, int currSum, HashMap<Integer, Integer> map){
    if(root == null) return 0;

    int res = 0;

    currSum += root.val;
    if(map.containsKey(currSum-targetSum)) res += map.get(currSum-targetSum);
    map.put(currSum, map.getOrDefault(currSum, 0) + 1);
    res += rootSum2(root.left, targetSum, currSum, map);
    res += rootSum2(root.right, targetSum, currSum, map);
    map.put(currSum, map.get(currSum) - 1);
    return res;
}

时间复杂度和空间复杂度都是O(N)O(N)