437. 路径总和 III

问题描述

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

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

分析

暴力解法,枚举每个结点开始是否有符合题意的路径,需要dfs枚举起点,从起点开始枚举路径还是dfs,所以是两层dfs。值得注意的是,因为题目中有负数,限制了剪枝:

  • 当当前路径结点和大于target时,不能return,因为下一个结点可能是负数,会使得当前路径和再减小
  • 当找到res时,不能return,因为下一个结点可能是1,再下一个结点可能是-1,于是还有答案

法一、暴力枚举,两次递归

class Solution {
public:
    long long res = 0;
    int target_sum = 0;
    // 从当前结点开始寻找答案路径
    void solve(TreeNode* root, long long x) {
        if (root == nullptr) {
            return ;
        }
        x += root->val;
        // if (x > target_sum) {
        //     return ;
        // }
        if (x == target_sum) {
            res++;
            // return ;
        }
        solve(root->left, x);
        solve(root->right, x);
    }

    void dfs(TreeNode* root) {
        if (root == nullptr) {
            return ;
        }
        solve(root, 0);
        dfs(root->left);
        dfs(root->right);
    }

    int pathSum(TreeNode* root, int targetSum) {
        this->target_sum = targetSum;
        dfs(root);
        return res;
    }
};

法二、前缀和+dfs

暴力方法中存在着许多重复计算,判断路径和是否等于某个值,显然想到前缀和。
用um记录在当前路径上从根结点开始的前缀和,由于cur_sum - prefix = sum,所以dfs到每个结点时,检索cur_sum - sum的数量即可,加到res中。而um就是存放当前路径上每个前缀和出现的次数。

class Solution {
public:
    unordered_map<long long, int> um; // <在该路径上根结点开始的路径和,出现次数>
    int res = 0;
    int target_sum = 0;
    void solve(TreeNode* root, long long cur_sum) {
        if (root == nullptr) {
            return ;
        }
        cur_sum += root->val;
        if (um.count(cur_sum - target_sum) != 0) { // 注意,这里的顺序,应该先判断res,然后再把当前cur_sum插入到um
            res += um[cur_sum-target_sum];
        }
        if (um.count(cur_sum) == 0) {
            um.insert(make_pair(cur_sum, 1));
        } else {
            um[cur_sum]++;
        }
        solve(root->left, cur_sum);
        solve(root->right, cur_sum);
        um[cur_sum]--; // 回溯
    }

    int pathSum(TreeNode* root, int targetSum) {
        this->target_sum = targetSum;
        um.insert(make_pair(0,1));
        solve(root, 0);
        return res;
    }
};
posted @   saulstavo  阅读(8)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示