LeetCode--sum-root-to-leaf-numbers

题目描述


Given a binary tree containing digits from0-9only, each root-to-leaf path could represent a number.

An example is the root-to-leaf path1->2->3which represents the number123.

Find the total sum of all root-to-leaf numbers.

For example,

    1
   / \
  2   3


The root-to-leaf path1->2represents the number12.
The root-to-leaf path1->3represents the number13.

Return the sum = 12 + 13 =25.

链接:https://www.nowcoder.com/questionTerminal/185a87cd29eb42049132aed873273e83
来源:牛客网

/*我觉得这个题目和剑指offer中的一道题目非常相似。先说这个题:
解题思路:从根结点开始,当每访问到一个结点,我们把该结点添加到路径上,并"累加"
该结点的值,这里"累加"的含义指的是按照题目的要求组成相应的数字即"左移"后相加。
如果该结点为叶结点,那么一条路径搜索完成,将当前所得结果累加。如果当前不是叶子
结点,则继续访问它 的子结点。当前结点访问结束后,递归函数将自动回到它的父结点。
因此我们在函数退出之前要在路径上"删除"当前结点,做法就是将当前路径值/10,以确
保返回父结点时路径刚好是从根结点到父结点的路径。我们不难看出保存路径的数据结构
实际上是一个栈,因为路径要与递归调用状态一致,而递归调用的本质就是一个压栈和出
栈的过程。*/
class Solution {
public:
    void sumNumbersCore(TreeNode *root, int &pathNum, int &sum) {
        if(root){
            pathNum = pathNum * 10 + root->val;
            //如果是叶子节点,一条路径搜索完成,累加到sum
            if(!root->left && !root->right){
                sum += pathNum;              
            }
            //如果不是叶子节点,则遍历它的子结点
            else{
                if(root->left)
                    sumNumbersCore(root->left, pathNum, sum);
                if(root->right)
                    sumNumbersCore(root->right, pathNum, sum);
            }
            //返回父结点之前,路径上“删除”当前节点
            pathNum /= 10;                    
        }
    }
     
    int sumNumbers(TreeNode *root) {
        int pathNum = 0;
        int sum = 0;
        sumNumbersCore(root, pathNum, sum);
        return sum;
    }
};
 
/*剑指offer面试题25:输入一棵二叉树和一个整数,打印出二叉树中结点值的和为输入
整数的所有路径。从树的根结点开始往下一直到叶节点所经过的结点形成一条路径。
解题思路:从根结点开始,当每访问到一个结点,我们把该结点添加到路径上,并累加
该结点的值。如果该结点为叶结点并且路径中结点值的和刚好等于输入的整数,则当前
路径符合要求,我们把它打印出来。如果当前不是叶子结点,则继续访问它的子结点。
当前结点访问结束后,递归函数将自动回到它的父结点。因此我们在函数退出之前要在
路径上删除当前结点并减去当前结点的值,以确保返回父结点时路径刚好是从根结点到
父结点的路径。我们不难看出保存路径的数据结构实际上是一个栈,因为路径要与递归
调用状态一致,而递归调用的本质就是一个压栈和出栈的过程。*/
class Solution {
public:
    void hasPathSumCore(TreeNode *root, int ¤tSum, int target, bool &flag){
        if(root){
            currentSum += root->val;
            //如果当前结点是叶子节点并且路径上结点的和等于target
            if(!root->left && !root->right){
                if(currentSum == target)
                    flag = true;
            }
            //如果不是叶子结点,则遍历它的子结点
            else{
                if(root->left)
                    hasPathSumCore(root->left, currentSum, target, flag);
                if(root->right)
                    hasPathSumCore(root->right, currentSum, target, flag);
            }
            //返回父结点之前,在路径上删除当前结点
            currentSum -= root->val;
        }
    }
     
    bool hasPathSum(TreeNode *root, int sum) {
        int currentSum = 0;
        bool flag = false;
        hasPathSumCore(root, currentSum, sum, flag);
        return flag;
    }
};
 
/*如果我们要求的再严格一些,输出二叉树中和为某一值的路径,其实可以用同一种思路
去解,可以沿用上面的代码,只需略作修改:*/
class Solution {
public:
    void hasPathSumCore(TreeNode *root, int ¤tSum, int target,  vector<int> &tempPath, vector<vector<int>> &paths){
        if(root){
            tempPath.push_back(root->val);
            currentSum += root->val;
            //如果是叶子结点,并且路径和等于target,保存当前路径
            if(!root->left && !root->right){
                if(currentSum == target)
                    paths.push_back(tempPath);              
            }
            //如果不是叶子结点,遍历其子结点
            else{
                if(root->left)
                    hasPathSumCore(root->left,currentSum,target,tempPath,paths);
                if(root->right)
                    hasPathSumCore(root->right,currentSum,target,tempPath,paths);
            }
            //返回到父结点之前,在路径上pop_back()当前节点,
            //相应的在路径和中减去当前节点的val。
            currentSum -= root->val;
            tempPath.pop_back();
        }
    }
     
    vector<vector<int> > pathSum(TreeNode *root, int sum) {
        int currentSum = 0;
        vector<vector<int>> paths;
        vector<int> tempPath;
        hasPathSumCore(root, currentSum, sum, tempPath, paths);
        return paths;
    }
};





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值