力扣437路径总和III

题目链接:437. 路径总和 III - 力扣(LeetCode)

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

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

示例 1:

复制代码
输入:root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8
输出:3
解释:和等于 8 的路径有 3 条,如图所示。

示例 2:

复制代码
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:3

提示:

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

每一条路径可视为一个数组,那么这题就变成了统计在数组中和为target的子序列的数量,显然使用前缀和

首先,要得到每一条路径所经过的节点值,需要使用深度优先搜索

当我们搜索到节点node时,计算出其前缀和为curr,我们希望在根节点root到node之间,存在一个节点node1,使得node1到node的和为target,那么这就意味着node1的前缀和为curr-target

为了记录数量,我们使用哈希表。键为前缀和,值为出现次数

遍历到节点node时,看哈希表中是否存在curr-target这个键,如果存在,记录curr-target这个路径和在这个路径的出现次数。再递归统计左右子树中出现目标值的次数,最后回溯,进入另一个分支即可。

C++

cpp 复制代码
/**
 * 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 {
public:
    unordered_map<uint64_t,int>cnt;//键:前缀和;值:出现次数
    int dfs(TreeNode*root,uint64_t curr,int target) {
        if(!root) return 0;
        int res=0;
        curr+=root->val;
        if(cnt.count(curr-target)) {
            //如果存在curr-target这个键
            res=cnt[curr-target];//那么res为在这条路径上的出现次数
        }
        cnt[curr]++;
        res+=dfs(root->left,curr,target);
        res+=dfs(root->right,curr,target);
        cnt[curr]--;//回溯
        return res;
    }
    int pathSum(TreeNode* root, int targetSum) {
        cnt[0]=1;//对于根节点来说,它的前缀和为0,因此算一条路径
        return dfs(root,0,targetSum);
    }
};

Java

java 复制代码
import java.util.HashMap;
import java.util.Map;

class Solution {

    public static 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;
        }
    }

    private int ans;
    
    public int pathSum(TreeNode root, int targetSum) {
        //key: 从根节点到该节点的路径和
        //value: 该路径和的出现次数
        Map<Long,Integer> cnt = new HashMap();
        cnt.put(0L,1);
        dfs(root,0L,targetSum,cnt);
        return ans;
    }
  
    //s是根节点到当前节点的路径和(不包括当前节点)
    private void dfs(TreeNode node, long s, int targetSum, Map<Long,Integer> cnt) {
        if(node == null) {
            return;
        }

        s += node.val;
        ans += cnt.getOrDefault(s - targetSum, 0); //前缀和
        cnt.merge(s, 1, Integer::sum); //cnt[s]++

        //如果merge在ans增加之前?只有一种情况会有问题,那就是 targetSum 为0,因为后续ans += cnt[s]
        //如果 targetSum 为0,假设根节点值为1,先把cnt[1]增加1,ans再变为1,但并不存在路径和为0的路径
        dfs(node.left, s, targetSum, cnt);
        dfs(node.right, s, targetSum, cnt);
        //回溯
        cnt.merge(s, -1, Integer::sum); //该节点的子节点全部统计完毕,完成使命
    }
}

Go

Go 复制代码
package main

type TreeNode struct {
    Val   int
    Left  *TreeNode
    Right *TreeNode
}

func pathSum(root *TreeNode, targetSum int) (ans int) {
    cnt := map[int]int{0:1}
    var dfs func(*TreeNode, int)
    dfs = func(node *TreeNode, s int) {
        if node == nil {
            return
        }
        s += node.Val
        ans += cnt[s - targetSum]
        cnt[s]++
        dfs(node.Left, s)
        dfs(node.Right, s)
        cnt[s]--
    }
    dfs(root, 0)
    return ans
}
相关推荐
AI科技星1 小时前
乖乖数学·全域超复数统一场论:五大核心门槛与全套标准定量数据
人工智能·python·算法·金融·全域数学
weedsfly1 小时前
单例模式在前端中的正确打开方式
前端·javascript·面试
帅次2 小时前
Android 高级工程师面试:网络与数据层 近1年高频追问 18 题
android·网络·okhttp·面试·retrofit·gilde
Frostnova丶2 小时前
(13)LeetCode 53. 最大子数组和
算法·leetcode·职场和发展
什巳2 小时前
JAVA练习277- 找到字符串中所有字母异位
java·开发语言·算法·leetcode
机器学习之心2 小时前
基于遗传粒子群混合算法的无人机三维路径规划:Matlab 实现与多算法对比分析
算法·matlab·无人机·无人机三维路径规划·遗传粒子群混合算法
本王是暴君2 小时前
AutoMem:把 Agent Memory 变成可训练的记忆管理技能
人工智能·算法·数据挖掘
zmzb01032 小时前
C++课后习题训练记录Day154
数据结构·c++·算法
木木子228 小时前
# 密码强度检测深度解析:正则表达式实时分析、多维度评分算法与可视化反馈
mysql·算法·华为·正则表达式·harmonyos
Sw1zzle10 小时前
算法入门(四):二叉树 - 递归遍历三件套
算法·leetcode