LeetCode 437 路径总和III

该博客讨论了一种解决二叉树路径和等于给定值的问题,通过使用回溯法和前缀和优化策略,实现了在O(n)时间复杂度内找到满足条件的路径总数。文章详细解释了两种方法,一种是传统的递归回溯,另一种是利用HashMap减少重复计算,提高了效率。
摘要由CSDN通过智能技术生成

题目

给定一个二叉树,它的每个结点都存放着一个整数值。找出路径和等于给定数值的路径总数。

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

二叉树不超过1000个节点,且节点数值范围是 [-1000000,1000000] 的整数。

示例

root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8

10

5   -3
/ \   
3   2   11
/ \   
3  -2   1
返回 3。和等于 8 的路径有:
1.  5 -> 3
2.  5 -> 2 -> 1
3.  -3 -> 11

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/path-sum-iii

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路:回溯法 + 前缀和

可以用递归来做,相当于先序遍历二叉树,对于每一个节点都有记录了一条从根节点到当前节点到路径,同时用一个变量 curSum 记录路径节点总和,然后看 curSum 和 sum 是否相等,相等的话结果 res 加1,不等的话继续查看子路径和有没有满足题意的,做法就是每次去掉一个节点,看路径和是否等于给定值,注意最后必须留一个节点,不能全去掉了,因为如果全去掉了,路径之和为0,而如果给定值刚好为0的话就会有问题

class Solution {
    List<TreeNode> path = new ArrayList<>();
    int count;
    public int pathSum(TreeNode root, int targetSum) {
        if(root == null) return 0;
        dfs(root, targetSum, 0, path);
        return count;
    }
    public void dfs(TreeNode root, int targetSum, int currSum, List<TreeNode> path){
        if(root == null) return;
        currSum += root.val;
        path.add(root);
        if(currSum == targetSum) count++;
        int tmp = currSum;
        for(int i = 0; i < path.size() - 1; i++){
            tmp -= path.get(i).val;
            if(targetSum == tmp) count++;
        }
        dfs(root.left, targetSum, currSum, path);
        dfs(root.right, targetSum, currSum, path);
        path.remove(path.size() -1);
    }
}

时间复杂度:O(n^2)
空间复杂度:O(n)

还可以对上面的方法进行一些优化,来去掉一些不必要的计算,可以用 HashMap 来建立路径之和跟其个数之间的映射,即路径之和为 curSum 的个数为 m[curSum],这里需要将 m[0] 初始化为1,相当于前缀和为0的路径有1条。在递归函数中,首先判空,若为空,直接返回0。然后就是 curSum 加上当前结点值。由于此时 curSum 可能已经大于了目标值 sum,所以用 curSum 减去 sum,并去 HashMap 中查找这个差值的映射值,若映射值大于0的话,说明存在结束点为当前结点且和为 sum 的路径,这就相当于累加和数组快速求某个区域和的原理。当 curSum 等于 sum 的时候,表明从根结点到当前结点正好是一条符合要求的路径,此时 res 应该大于0,这就是为啥要初始化 m[0] 为1的原因

class Solution {
    public int pathSum(TreeNode root, int targetSum) {
        if(root == null) return 0;
        Map<Integer, Integer> prefixSum = new HashMap<>();
        prefixSum.put(0,1);
        return dfs(root, targetSum, 0,prefixSum);
    }
    public int dfs(TreeNode root, int targetSum, int currSum, Map<Integer, Integer> prefixSum){
        if(root == null) return 0;
        currSum += root.val;
        int res = prefixSum.getOrDefault(currSum - targetSum,0);
        prefixSum.put(currSum,prefixSum.getOrDefault(currSum,0) + 1);
        res += dfs(root.left,targetSum, currSum, prefixSum) + dfs(root.right, targetSum,currSum,prefixSum);
        prefixSum.put(currSum, prefixSum.get(currSum) - 1);
        return res;
    }
}

时间复杂度:O(n)
空间复杂度:O(n)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值