2021年9月28日-路径总和 III

路径总和 III

方法一:直接递归

首先我们用递归解决从根节点出发的路径和为 target 的路径数,

然后我们在遍历每一个节点,每个节点都做一遍上述的递归,将答案累加即使最终答案

中等题的递归一次不行我们就多拆几次?

不过直接递归会做大量重复计算

private int sum = 0;

public int pathSum(TreeNode root, int targetSum) {
    if (root == null) {
        return 0;
    }
    sum += help(root, targetSum);
    pathSum(root.left, targetSum);
    pathSum(root.right, targetSum);
    return sum;
}

private int help(TreeNode root, int targetSum) {
    if (root == null) {
        return 0;
    }
    int res = 0;
    if (root.val == targetSum) {
        res++;
    }
    return res
            + help(root.left, targetSum - root.val)
            + help(root.right, targetSum - root.val);
}

方法二:前缀和 + 回溯

当进行深度遍历时,我们使用一个 map 来记录每个节点的前缀和和这个和出现的次数。前缀和指的是从根节点到某一节点(不包含这个节点)上的所有节点值之和。如果遍历到了节点 A,如何得知以 A 节点为尾节点的目标路径的数量呢?我们知道: A 的前缀和 + A 的值 - 目标路径第一个节点的前缀和等于 targetSum,所以只需查看 map 中 key 等于 A 的前缀和 + A 的值 - targetSum 有几个就行了。不过一定要记得回溯,因为这个路径只能从父亲到儿子。

// 前缀和 + 回溯
public int pathSumPro(TreeNode root, int targetSum) {
    // 记录前缀和,key = 前缀和 value = 个数
    HashMap<Integer, Integer> prefix = new HashMap<>();
    prefix.put(0, 1);
    return dfs(root, prefix, 0, targetSum);
}

private int dfs(TreeNode root, Map<Integer, Integer> prefix, int curr, int targetSum) {
    if (root == null) {
        return 0;
    }
    int res = 0;
    curr += root.val;
    res = prefix.getOrDefault(curr - targetSum, 0);
    prefix.put(curr, prefix.getOrDefault(curr, 0) + 1);
    res += dfs(root.left, prefix, curr, targetSum);
    res += dfs(root.right, prefix, curr, targetSum);
    // 访问完左右子树要恢复状态
    prefix.put(curr, prefix.getOrDefault(curr, 0) - 1);
    return res;
}

茫茫题海,何时是岸(┬┬﹏┬┬)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值