48 路径总和 III

路经总和 III

    • 题目规定了寻路方向(不能折返,是单源向下探路,符合DFS)
      • 模板1
    • 题解1 DFS
      • 更好理解题意的版本
    • 题解2 前缀和(重点记忆)
      • 前缀和 = 由根结点到当前结点的路径上所有节点的和(不含当前结点)

给定一个二叉树的根节点 root ,和一个整数 targetSum ,求该二叉树里节点值之和等于 targetSum路径的数目。

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

48 路径总和 III_第1张图片
提示:

  • 二叉树的节点个数的范围是 [0,1000]
  • − 1 0 9 -10^9 109 <= Node.val <= 1 0 9 10^9 109
  • -1000 <= targetSum <= 1000

题目规定了寻路方向(不能折返,是单源向下探路,符合DFS)

模板1

题解1 DFS

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
    int pathnum = 0;
public:
	// 题目node.val 可能是9位数,注意long
    void dfs(TreeNode* root, long sum){
        if(! root) return;
        sum -= root->val;

        if(0 == sum) pathnum++;
        dfs(root->left, sum);
        dfs(root->right, sum);
        
    }
    int pathSum(TreeNode* root, int targetSum) {
        if(! root) return 0;
        dfs(root, targetSum);
        pathSum(root->left, targetSum);
        pathSum(root->right, targetSum);
        return pathnum;
    }
};

48 路径总和 III_第2张图片

更好理解题意的版本

class Solution {
public:
    int dfs(TreeNode* root, long sum){
        if(! root) return 0;
        int ret = 0;

        if(root->val == sum)
            ret ++;
        
        ret += dfs(root->left, sum-root->val);
        ret += dfs(root->right, sum-root->val);
        
        return ret;
    }
    int pathSum(TreeNode* root, int targetSum) {
        if(! root) return 0;
        // 以当前结点为起点,递归向下搜索
        int ret = dfs(root, targetSum);
        // 单源——以所有结点为源,找完可能的路径
        ret += pathSum(root->left, targetSum);
        ret += pathSum(root->right, targetSum);
        return ret;
    }
};

48 路径总和 III_第3张图片

题解2 前缀和(重点记忆)

前缀和 = 由根结点到当前结点的路径上所有节点的和(不含当前结点)

class Solution {
    unordered_map<long, int> prefixSum;
public:
    int dfs(TreeNode* root, long sum, int targetSum){
        if(! root) return 0;
        int ret = 0;
        // 当前结点对应的前缀和
        sum += root->val;
        // 以当前节点为尾结点的某个前缀和存在 == 有满足条件的路径
        if(prefixSum.count(sum - targetSum)){
            ret = prefixSum[sum - targetSum];
        }
        // 保存当前结点往下搜索
        prefixSum[sum] ++;
        ret += dfs(root->left, sum, targetSum);
        ret += dfs(root->right, sum, targetSum);
        // 回溯:退出当前结点
        prefixSum[sum] --;

        return ret;
    } 
    int pathSum(TreeNode* root, int targetSum) {
        // 因为用的是减法,避免sum = targetSum时为0
        prefixSum[0] = 1;
        return dfs(root, 0, targetSum);
    }
};

48 路径总和 III_第4张图片

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