leetcode437 路径总和3 寻找总和为targetsum的路径

两层dfs 第一层dfs找根节点,第二层dfs从根节点开始找路径
时间复杂度O(n2)

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
void dfs(struct TreeNode* proot,int sum,int*ans,int targetSum)
{
    if(sum==targetSum)
       (*ans)++;
    if(proot->left!=NULL)
    dfs(proot->left,sum+proot->left->val,ans,targetSum);
    if(proot->right!=NULL)
    dfs(proot->right,sum+proot->right->val,ans,targetSum);
    return;
}
void dfs_out(struct TreeNode* proot,int* ans,int targetSum)
{
    if(proot==NULL)
       return;
    dfs(proot,proot->val,ans,targetSum);
    dfs_out(proot->left,ans,targetSum);
    dfs_out(proot->right,ans,targetSum);
    return;
}
int pathSum(struct TreeNode* root, int targetSum){
    int ans=0;
    dfs_out(root,&ans,targetSum);
    return ans;
}

若用dfs的返回值表示在此根节点下满足条件的路径,用dfs_out的返回值表示所有的路径数,则ans可以省去,同时若用delta表示当前的和与targetsum的差值,则sum也可以省去

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

int dfs(struct TreeNode* proot,int delta)    
{
    int ans=0;
    if(delta==0)
    ans++;
    if(proot->left)
       ans+=dfs(proot->left,delta-proot->left->val);
    if(proot->right)
       ans+=dfs(proot->right,delta-proot->right->val);
    return ans;
}
int dfs_out(struct TreeNode* proot,int targetSum)
{
    if(proot==NULL)
    return 0;
    int ans=0;
    ans+=dfs(proot,targetSum-proot->val);
    ans+=dfs_out(proot->left,targetSum);
    ans+=dfs_out(proot->right,targetSum);
    return ans;
}
int pathSum(struct TreeNode* root, int targetSum){
    return dfs_out(root,targetSum);
}

同时也可用pathSum函数来代替dfs_out函数

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
int dfs(struct TreeNode* proot,int delta)    
{
    int ans=0;
    if(delta==0)
    ans++;
    if(proot->left)
       ans+=dfs(proot->left,delta-proot->left->val);
    if(proot->right)
       ans+=dfs(proot->right,delta-proot->right->val);
    return ans;
}
int pathSum(struct TreeNode* root, int targetSum){
    if(root==NULL)
    return 0;
    int ans=0;
    ans+=dfs(root,targetSum-root->val);
    ans+=pathSum(root->left,targetSum);
    ans+=pathSum(root->right,targetSum);
    return ans;
}

还可以进行优化,因为当用dfs计算一段路径上的和的时候是很容易发生重复计算的,可以用前缀和进行优化
官方题解
代码中的map实际上存储的是当前路径上的前缀和,所以当回溯的时候,要把当前结点的前缀和在map中去掉,因为不是下一条路径上的了
mp[0]=1实际上是指从结点pk到根节点root这条路径符合条件,这如果要用前缀和的形式pre[pk]-pre[x]的话x就是根节点的“前一个结点”,“前一个结点”的前缀和必然是0,所以前缀和为0的结果必然有1个

/**
 * 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<long long,int> mp;
    int dfs(TreeNode* root,int curr,int targetSum)
    {
        if(root==NULL)
        return 0;
        int ans=0;
        curr=curr+root->val;
        if(mp.count(curr-targetSum))
        {
           ans+=mp[curr-targetSum];
        }
        mp[curr]++;
        ans+=dfs(root->left,curr,targetSum);
        ans+=dfs(root->right,curr,targetSum);
        mp[curr]--;
        return ans;
    }
    int pathSum(TreeNode* root, int targetSum) {
        mp[0]=1;
        return dfs(root,0,targetSum);
    }
};

时间复杂度O(n)

上一篇:27. 二叉树的镜像


下一篇:剑指offer部分题解