LeetCode 437 – 路径总和 III

题目描述

给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum 的 路径 的数目。

路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。

题目分析

前序遍历,记录前面走过的结点,以当前结点为终点,向前累加。但会发现在计算累加和这里存在很多重复计算,时间复杂度 O(n * n).
设从根结点到当前结点的和是 sum,使用 HashMap 存储以根结点为起点的前缀和。由于存在负数的结点值,所以同一个前缀和可能会存在多个。
对于一个结点,如果它是 targetSum 路径的终点,那么 targetSum + 前缀和 = sum。因此只要查看 map 中是否存在 sum – targetSum 即可。
时间复杂度 O(n)

Java

private int count = 0;
private HashMap<Long, Integer> preSum;

// 前序遍历 + 前缀和
// 时间复杂度 O(n)
public int pathSum(TreeNode root, int targetSum) {
    count = 0;
    preSum = new HashMap<>();
    preSum.put(0L, 1);
    dfs(root, targetSum, 0);
    return count;
}

private void dfs(TreeNode root, int targetSum, long sum) {
    if (root == null) {
        return;
    }
    sum += root.val;
    count += preSum.getOrDefault(sum - targetSum, 0);
    preSum.put(sum, preSum.getOrDefault(sum, 0) + 1);
    dfs(root.left, targetSum, sum);
    dfs(root.right, targetSum, sum);
    preSum.put(sum, preSum.getOrDefault(sum, 0) - 1);
}

Kotlin

private val preSum = HashMap<Long, Int>()
private var count = 0

fun pathSum(root: TreeNode?, targetSum: Int): Int {
    count = 0
    preSum.clear()
    preSum[0L] = 1
    dfs(root, targetSum, 0)
    return count
}

private fun dfs(root: TreeNode?, targetSum: Int, sum: Long) {
    if (root == null) {
        return
    }

    val newSum = sum + root.`val`
    count += preSum.getOrDefault(newSum - targetSum, 0)
    preSum[newSum] = preSum.getOrDefault(newSum, 0) + 1
    dfs(root.left, targetSum, newSum)
    dfs(root.right, targetSum, newSum)
    preSum[newSum] = preSum.getOrDefault(newSum, 0) - 1
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部