题解 | 二叉树中和为某一值的路径(三)

二叉树中和为某一值的路径(三)

https://www.nowcoder.com/practice/965fef32cae14a17a8e86c76ffe3131f

/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 *	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
#include <unordered_map>
class Solution {
public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 
     * @param root TreeNode类 
     * @param sum int整型 
     * @return int整型
     */
    
    int res = 0;
    unordered_map<int, int> mp;//key为curSum值,value为这个值对应的路径条数(在经过当前节点的路径中的条数)
    void dfs(TreeNode* node, int sum, int curSum){
        if(!node) return;
        //此点和之前的任意个连续节点连起来是否是sum
        curSum += node->val;
        //不能留到子树给它算只有它一个怎么办,因为可能绝后
        //找到为0也没关系,加上去res不会增加,有一个条件语句主要是避免造出没有的mp来?(不是默认为0吗?)
        res += mp[curSum-sum];
        
        ++mp[curSum];//放在res += mp[curSum-sum];后面加,因为curSum相当于这个节点和下个节点交界处,
       // 若提前把它放入,会得到0(一个节点都没有的假路径),如果sum为0就会出现问题
        if(node->left)  dfs(node->left, sum, curSum);
        if(node->right) dfs(node->right, sum, curSum);
        --mp[curSum];
    }
    int FindPath(TreeNode* root, int sum) {
        // write code here
        //为了保证不会先出现后面的,应该用前序遍历
        if(!root) return 0;
       mp[0] = 1;//第一个间隙(第一个节点的头部空隙)
        dfs(root, sum, 0);
        return res;
    }
};

方法一:

往深处遍历,保证到该节点时是从双亲节点过来的,没有受到兄弟姐妹侄女侄儿等的影响,所以用前序遍历。

计算总和是在节点之间而不是节点上,所以mp[0]=1;保证从根节点到某节点这条路径也被计算在内。

相对官方解法没有条件语句判断是否存在一条路径满足要求,因为unordered_map<int, int>这样的结构初始化时会是int的默认值,在c++中int默认会是0(仅限于在容器中的情况,如果是直接int i; i会是任意值)。

空间复杂度和时间复杂度都是O(n)。

/**
 * struct TreeNode {
 *  int val;
 *  struct TreeNode *left;
 *  struct TreeNode *right;
 *  TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
class Solution {
  public:
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param root TreeNode类
     * @param sum int整型
     * @return int整型
     */
    int res = 0;
    void dfs(TreeNode* Node, int sum) {
        if (!Node) return;
        //这个点是一定需要的,后面的节点不能跳着要,走这条路,这条路上的节点都需要
        if (sum == Node->val) ++res;
        dfs(Node->left, sum - Node->val);
        dfs(Node->right, sum - Node->val);
    }

    int FindPath(TreeNode* root, int sum) {
        // write code here
        if (!root) return 0;
        queue<TreeNode*> q;
        q.push(root);
        while (!q.empty()) {
            TreeNode* temp = q.front();
            q.pop();//为什么不能和上一句用逗号隔开?
            /*在C++中,`q.pop()` 是一个返回类型为 `void` 的函数,
            逗号运算符用于在一行中执行多个表达式,并且返回最后一个表达式的值。
            由于 `q.pop()` 没有返回值,不能与 `q.front()` 一起使用逗号运算符。*/
            dfs(temp, sum);
            if (temp->left) q.push(temp->left);
            if (temp->right) q.push(temp->right);
        }
        return res;
    }
};

方法二:

首先遍历每一个节点,然后以每一个节点为头节点,看包含这个节点往下走有没有和为sum的路径。

因为每一个节点都会作为头节点,且递归会从每一节点作为头节点递归完整该节点全部子树(路径),所以以任何一个节点开头的路径都会被找到而且找全。

它不作为头节点时,会不会被祖先节点连成一条可用路径是祖先节点那次递归要考虑的。

第一重遍历随便什么方法都行,只是要每个节点都作为头节点一次。

第二重遍历必须前序遍历,遵循双亲到子的顺序。

时间复杂度为O(n^2)。空间复杂度为O(n)。

全部评论

相关推荐

独玖:同二本,建议咱俩一起重开
点赞 评论 收藏
分享
04-03 11:37
武汉大学 Java
高斯林的信徒:武大简历挂?我勒个骚岗
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务