2022-02-18(437. 路径总和 III)

这篇博客介绍了两种解决二叉树路径和问题的方法。方法一是通过递归遍历,分别计算节点及其子树的路径和;方法二是利用前缀和,借助HashMap存储中间结果,优化空间换取时间效率。文章详细阐述了这两种算法的实现思路,并提供了相关代码示例。
摘要由CSDN通过智能技术生成

方法1:遍历

/**
 * 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 int pathSum(TreeNode root, int targetSum) {
        if(root==null){
            return 0;
        }
        return thisNodeSum(root,targetSum)+pathSum(root.left,targetSum)+pathSum(root.right,targetSum);
    }
    public int thisNodeSum(TreeNode root,int targetSum){
        if(root==null){
            return 0;
        }
        int a=targetSum-root.val;
        int count=0;
        if(a==0){
            ++count;
        }
        count+=(thisNodeSum(root.left,targetSum-root.val)+thisNodeSum(root.right,targetSum-root.val));
        return count;
    }
}

方法2:前缀和(空间换时间)

主要学习的题解:https://leetcode-cn.com/problems/path-sum-iii/solution/dui-qian-zhui-he-jie-fa-de-yi-dian-jie-s-dey6/

1 前缀和:一个节点的前缀和就是该节点到根之间的路径和
2 HashMap的key是前缀和, value是该前缀和的节点数量,记录数量是因为有出现复数路径的可能
3 本质还是空间换时间,保存各种前缀和出现的次数。
即:要寻找的前缀和=根节点到当前节点的路径和-targetSum

/**
 * 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 {
    int wholeTargetSum;
    Map<Integer,Integer> map;
    public int pathSum(TreeNode root, int targetSum) {
        wholeTargetSum=targetSum;
        map=new HashMap<>();
        map.put(0,1);    //十分重要的一行,不然就不能从根节点开始算了
        return dfs(root,0);
    }
    public int dfs(TreeNode root,int pre){
        if(root==null){
            return 0;
        }

        int pathSum=pre+root.val;   //获取节点到当前节点root的路径和pathSum
        int needPrefix=pathSum-wholeTargetSum;  //得到需要的前缀和needPrefix
        int count=map.getOrDefault(needPrefix,0);   //得到needPrefix对应次数

         /*添加该前缀和到map中,给子节点使用
          这行代码不能放在 int count=map.getOrDefault(needPrefix,0); 之前,因为路径不能不包括任何节点
          */
        map.put(pathSum,map.getOrDefault(pathSum,0)+1);    
        count+=dfs(root.left,pathSum);
        count+=dfs(root.right,pathSum);
        map.put(pathSum,map.get(pathSum)-1);  //去除这个前缀和对应的次数

        return count;
    }
}






// class Solution {
//     Map<Integer, Integer> prefixMap;
//     int target;

//     public int pathSum(TreeNode root, int sum) {
//         prefixMap = new HashMap<>();
//         target = sum;

//         prefixMap.put(0, 1);
//         return recur(root, 0);
//     }

//     private int recur(TreeNode node, int curSum) {
//         if(node == null) {
//             return 0;
//         }

//         int res = 0;
//         curSum += node.val;

//         res += prefixMap.getOrDefault(curSum - target, 0);
//         prefixMap.put(curSum, prefixMap.getOrDefault(curSum, 0) + 1);

//         int left = recur(node.left, curSum);
//         int right = recur(node.right, curSum);

//         res = res + left + right;

//         prefixMap.put(curSum, prefixMap.get(curSum) - 1);

//         return res;
//     }
// }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值