LeetCode437. 路径总和 III

【举一反三】:在二叉树中找到累加和为指定值的最长路径长度  ------ 左神P115

☆☆☆☆思路1:双重递归,第一个递归用来遍历这些节点,这二个递归用来处理这些节点,进行dfs。

    思路1的缺点是存在大量重复计算,时间效率差

☆☆☆☆☆思路2:前缀和 递归回溯。  时间复杂度为O(n),空间复杂度为O(n)

代码1.1:

class Solution {
    // 在以root为根节点的二叉树中,寻找和为sum的路径,返回这样的路径个数
    public int pathSum(TreeNode root, int sum) {
        if (root == null) return 0;

        // 每一个节点寻找的路径数 由 三部分构成
        int res = findPath(root, sum);
        res += pathSum(root.left, sum);
        res += pathSum(root.right, sum);
        return res;
    }
    // 在以node为根节点的二叉树中,寻找包含node的路径,和为num
    // 返回这样的路径个数
    private int findPath(TreeNode node, int num) {
        if (node == null) return 0; // 可以一直搜索到null
        int res = 0;

        if (node.val == num) {
            res += 1;  // 不能直接return,因为值有负数的情况
        }
        res += findPath(node.left, num - node.val);
        res += findPath(node.right, num - node.val);

        return res;
    }
}

代码1.2:

class Solution {
    int count = 0;
    public int pathSum(TreeNode root, int sum) {
        if (root == null) return 0;
        dfs(root, sum);
        pathSum(root.left, sum);
        pathSum(root.right, sum);
        return count;
    }
    private void dfs(TreeNode node, int num) {
        if (node == null) return;
        if (node.val == num) {
            count ++;
        }
        dfs(node.left, num - node.val);
        dfs(node.right, num - node.val);
    }
}

代码2:前缀和, 参考:前缀和,递归,回溯

class Solution {
    public int pathSum(TreeNode root, int sum) {
        // key是前缀和, value是大小为key的前缀和出现的次数
        Map<Integer,Integer> map = new HashMap<>();
        // 当(pathSum-sum = 0)时,说明当前路径符合要求,res + 1
        map.put(0, 1);
        return dfs(root, map, 0, sum);
    }
    private int dfs(TreeNode root, Map<Integer,Integer> map, int curSum, int target) {
        // 1.递归终止条件
        if (root == null) return 0;
        // 2.本层要做的事情
        curSum += root.val;
        int res = 0;
        // currSum-target相当于找路径的起点,起点的sum+target=currSum,当前点到起点的距离就是target
        res += map.getOrDefault(curSum - target, 0);
        map.put(curSum, map.getOrDefault(curSum, 0) + 1);
        // 3.进入下一层
        res += dfs(root.left, map, curSum, target);
        res += dfs(root.right, map, curSum, target);
        // 4.回到本层,左右子树遍历完后,恢复状态(因为这个路径不可能是别的路径的前缀了)
        map.put(curSum, map.get(curSum) - 1);
        return res;
    }
}
原文地址:https://www.cnblogs.com/HuangYJ/p/14187377.html