路径总和Ⅲ

LeetCode 437

路径总和

给定一个二叉树,它的每个结点都存放着一个整数值。

找出路径和等于给定数值的路径总数。

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

二叉树不超过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

解法:递归

解题思路:

对每一颗树,我们都能从根结点找到往下的所有路径,每当我们找到一条路径,就积累该路径上的值,只要该值满足条件,就将全局变量res+1,然后继续往下找结点,直到所有路径都找完,此时我们以及将一棵树从根结点的所有路径找完,接下来就要找以左右孩子结点为根结点的树的所有路径和

代码如下:

/**
* Definition for a binary tree node.
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode(int x) { val = x; }
* }
*/
class Solution {
    private int res = 0;
    public int pathSum(TreeNode root, int sum) {
        PathSum(root,sum); //以root为根结点的树
        return res;
    }
    public void PathSum(TreeNode root, int sum)
    {
        if(root==null)
            return;
        pathSum(root,sum,0); //求路径和
        PathSum(root.left,sum); //以左孩子为根结点的树
        PathSum(root.right,sum); //以右孩子为根结点的树
    }
    public void pathSum(TreeNode root, int sum, int num)
    {
        if(root==null) //为空就返回
            return;
        num+=root.val; //积累路径和
        if(sum==num) //如果满足条件,结果加1
        {
            res++;
        }    
        pathSum(root.left,sum,num); //往下找
        pathSum(root.right,sum,num);
    }
}

解法2:前缀和

解题思路:

如果我们保存每一个结点从根节点下来的路径的前缀和,那么我们就知道

如果有两个结点的前缀和之差为sum(注意,必须是下面的结点减去上面的结点),那么这两个结点之间的路径就是满足条件的路径,因此我们只要用一个HashMap来保存每一个前缀和的个数,就能找到满足条件的路径总和了

代码如下:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int pathSum(TreeNode root, int sum) {
        // key是前缀和, value是大小为key的前缀和出现的次数
        Map prefixSumCount = new HashMap<>();
        // 前缀和为0的一条路径
        prefixSumCount.put(0, 1);
        // 前缀和的递归回溯思路
        return recursionPathSum(root, prefixSumCount, sum, 0);
    }
    private int recursionPathSum(TreeNode node, Map prefixSumCount, int target, int currSum) {
        // 1.递归终止条件
        if (node == null) {
            return 0;
        }
        int res = 0;
        // 求出前缀和
        currSum += node.val;

        //将所有前缀和之差为sum的结点加到结果中
        res += prefixSumCount.getOrDefault(currSum - target, 0);
        // 更新路径上当前节点前缀和的个数
        prefixSumCount.put(currSum, prefixSumCount.getOrDefault(currSum, 0) + 1);

        // 3.进入下一层
        res += recursionPathSum(node.left, prefixSumCount, target, currSum);
        res += recursionPathSum(node.right, prefixSumCount, target, currSum);

        // 4.回到本层,恢复状态,去除当前节点的前缀和数量
        // 因为该节点是上面的结点的下面,所以它的前缀和不能被上面的结点来减,所以要去除掉
        prefixSumCount.put(currSum, prefixSumCount.get(currSum) - 1);
        return res;
    }
}

解法2来源

作者:burning-summer
链接:https://leetcode-cn.com/problems/path-sum-iii/solution/qian-zhui-he-di-gui-hui-su-by-shi-huo-de-xia-tian/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(树,算法,二叉树,数据结构,leetcode,java)