Leetcode算法学习日志-437 Path Sum III

Leetcode 437 Path Sum III

题目原文

You are given a binary tree in which each node contains an integer value.

Find the number of paths that sum to a given value.

The path does not need to start or end at the root or a leaf, but it must go downwards(traveling only from parent nodes to child nodes).

The tree has no more than 1,000 nodes and the values are in the range -1,000,000 to 1,000,000.

Example:

root = [10,5,-3,3,2,null,11,3,-2,null,1], sum = 8

      10
     /  \
    5   -3
   / \    \
  3   2   11
 / \   \
3  -2   1

Return 3. The paths that sum to 8 are:

1.  5 -> 3
2.  5 -> 2 -> 1
3. -3 -> 11

题意分析

在一棵二叉树上找和为sum的path,path必须是从上到下连续的一条,但起始和终止不一定要在root或leaf。求满足条件的path数。

解法分析

本题采用两种思路:

  • 深度优先搜索

本题的深度优先搜索思路类似于560 Subarray Sum,在深度优先的一条路上,每遇到一个节点,就将val加到sum中,并用一个unordered_map存储sum,以及sum出现的次数(算法中这一步要最后进行),将sum-target,得到的值作为key进入map搜索是否存在,如果存在,就说明累加和为sum-target的节点到本节点的中间path和为target,这样的path的个数为map[sum-target],并将该值加到全局变量count中。最后将sum放入map中,如果存在就将value加一。之后就递归搜索两个子节点,map通过传引用的方式传给下一层dfs,这样能大大节省时间开销,在两个dfs返回后,需要将map[sum]--,而对于sum来说,它是值传递,不改变原值。C++代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
private:
    int pcount;
    int target;
public:
    void dfsSum(TreeNode* root,int sum,unordered_map<int,int> &smap){//use the &smap to reduce time
        if(root==NULL)
            return;
        sum+=root->val;
        if(smap.count(sum-target))
            pcount+=smap[sum-target];
        smap[sum]++;//must behind the above sentence
        dfsSum(root->left,sum,smap);
        dfsSum(root->right,sum,smap);
        smap[sum]--;//smap is a &
    }
    int pathSum(TreeNode* root, int sum) {
        pcount=0;
        int pSum=0;
        target=sum;
        unordered_map<int,int> smap;//first is the sum, second is the path that sum to this sum from the root
        smap[0]=1;
        dfsSum(root,pSum,smap);
        return pcount;   
    }
};

  • 递归思想

递归思想就将大问题分解为小问题递归解决,总的问题为以root为根的数的path数,可以分解为三部分,第一部分为path包含root的path数,第二部分为path不包含root,左子树的path数,第三部分为path不包含root,右子树的path数。C++代码如下:

class Solution {
public:
    int containSum(TreeNode* root,int sum){//the path contains root and sums to sum
        if(root==NULL)
            return 0;
        if(root->val==sum)
            return 1+containSum(root->left,sum-root->val)+containSum(root->right,sum-root->val);
        return containSum(root->left,sum-root->val)+containSum(root->right,sum-root->val);
    }
    int pathSum(TreeNode* root, int sum) {
        if(root==NULL)
            return 0;
        return pathSum(root->left,sum)+pathSum(root->right,sum)+containSum(root,sum);
    }
};

注意containSum的结束条件,root->val==sum,此时的返回值还需继续向下递归,只是多加了1,因为val可能有负数,后面还有可能达到target。


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值