力扣437题:路径之和

力扣437题:路径之和

题目描述

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

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

输入输出样例

在这里插入图片描述

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

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

Tips

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

解法一,使用深度优先搜索DFS

//使用递归的方法进行实现,DFS(深度优先的算法)
class Solution{
public:
    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;
    }

    int dfs(TreeNode *root,long target)
    {
        //定义循环终止的条件
        if(!root)
        {
            return 0;
        }

        int ret=0;
        if(root->val==target)
        {
            ret++;
        }

        //若不相等,继续递归其左右的结点,目标值变成其剩余的结点的值
        ret+=dfs(root->left,target-root->val);
        ret+=dfs(root->right,target-root->val);
        return ret;
    }

};

解法二,使用前缀和

//使用前缀和 的思想实现
class Solution2
{
public:
    int pathSum(TreeNode *root,int targetSum)
    {
        //建立hash表存储前缀和的值和出现的次数
        //key:前缀和 value 出现的次数
        unordered_map<long long,int>maps;

        //初始化 hash 表
        //前缀和为0的一条路径
        maps[0]=1;
        return dfs(root,maps,targetSum,0);


    }

    //使用递归实现前缀和
    //从当前结点反推到根结点,有且只有一条路径,因为是树
    //若此前有和为currSum-target,而当前的和恰为currSum,两者的差肯定是target
    //前缀和对于当前路径是唯一的,当前记录的前缀和,在回溯结束,回到本层时进行去除,保证其不影响其他的分支
    int dfs(TreeNode *root,unordered_map<long long,int>&maps,int target,long long currSum)
    {

        //递归终止条件
        if(!root)
        {
            return 0;
        }

        //记录寻找到的次数
        int res=0;
        //记录当前路径找到的和
        currSum+=root->val;

        //查找当前路径上是否存在结点前缀和加target为currSum的路径
        //当前结点->root结点反推,有且仅有一条路径,如果此前有和为currSum-target,而当前和有为currSum,则两者差肯定为target
        //currSum-target相当于寻找路径的起点,起点的sum+target=currSum,当前点到点的距离就是target

        if(maps.count(currSum-target))
        {
            res=maps[currSum-target];
        }

        //更新路径上当前结点前缀和的个数
        maps[currSum]++;

        //进入下一层
        res+=dfs(root->left,maps,target,currSum);
        res+=dfs(root->right,maps,target,currSum);
        //回到本层,恢复状态,去除当前结点的前缀和数量
        maps[currSum]--;

        return res;

    } 
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值