[牛客网-Leetcode] #树中sum-root-to-leaf-numbers

Path from root node to leaf node and sum-root-to-leaf-numbers

Title description

Given a binary tree containing only the numbers 0-9, each path from the root node to the leaf node can be represented by a number.
For example, a path from the root node to the leaf node is 1->2->3, then this path is replaced by 123.
Find the sum of the numbers represented by all the paths from the root node to the leaf nodes
For example:
1↵ / ↵ 2 3
The path from the root node to the leaf node 1->2 Use the number 12 instead
of the path from the root node to the leaf node 1->3 Use The number 13 is replaced,
so the answer is 12+13=25

Given a binary tree containing digits from 0-9 only, 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.

Example

Example 1
input

{1,0}

Output

10

Example 2
input

{1,#,5}

Output

15

Problem-solving ideas

Idea 1: BFS

  • Find the path from all leaf nodes to the root node according to BFS, and then add them
  • Use mp to record the mapping of all children->parents, which is similar to the union search set, so that it can be traversed from the leaf node to the root node.
    • Note: It is not possible to create a parent->child mapping, because the parent may have multiple children, and the mapping must be unique, so it can only be one-to-one from child to parent
  • Use the leafNode array to save all the leaf nodes, and finally use the mp mapping to find the path sum of each leaf node, and accumulate
/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 * };
 */
#include "unordered_map"
class Solution {
    
    
public:
    int sumNumbers(TreeNode* root) {
    
    
        if(root == NULL) return 0;
        int res(0);
        queue<TreeNode*> myque;
        myque.push(root);
        //用于保存从叶节点到根节点的路径
        unordered_map<TreeNode*, TreeNode*> mp;  
        mp[root] = root;
        //用于保存所有的叶节点,方便遍历mp
        vector<TreeNode*> leafNode;
        
        while(!myque.empty()) {
    
    
            int size = myque.size();
            for(int i = 0; i < size; i ++) {
    
    
                TreeNode* temp = myque.front();
                myque.pop();
                //如果左右子树均为空,则添加进leafnode中
                if(!temp -> left && !temp -> right) {
    
    
                    leafNode.push_back(temp);
                }
                //如果有左右孩子,则添加 孩子->双亲 的映射
                if(temp -> left) {
    
    
                    myque.push(temp -> left);
                    mp[temp -> left] = temp;
                }
                if(temp -> right) {
    
    
                    myque.push(temp -> right);
                    mp[temp -> right] = temp;
                }
            }
        }
        //对每一个叶节点都计算其路径和,并累加
        for(auto node : leafNode) {
    
    
            int sum(0);  //记录每一个叶节点的路径和
            int temp(1);
            while(node != root) {
    
    
                sum += node -> val * temp;
                temp *= 10;
                node = mp[node];  //不断往根节点遍历
            }
            sum += root -> val * temp;  //最后加上根节点
            res += sum;
        }
        
        return res;
    }
};

Idea 2: Backtracking

  • Path: recorded in the track
  • Selection list: non-empty left and right subtrees
  • End condition: reach the leaf node, then accumulate
  • Note: Before the backtracking method solves the path problem of the tree, the root node must be added to the path
  • Supplement, the usage of accumulate function:
    • The header file of accumulate is:#include <numeric>

    • For example, for vector<int> vecan array, sum it up:
      int sum = accumulate(vec.begin(), vec.end(), 0)
      The result of the accumulation and sum is stored in sum. The first two parameters specify the range of the summation, and the third parameter specifies the initial value of the accumulation.

      You can also use accumulate to connect the elements in the string-type vector container:
      string sum = accumulate(v.begin() , v.end() , string(" "));
      the effect of this function call is: starting from an empty string, each element in the vec is connected into a string.

/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 * };
 */
#include<numeric>
class Solution {
    
    
public:
    int sumNumbers(TreeNode* root) {
    
    
        if(root == NULL) return 0;
        int res(0);
        vector<int> track;
        
        //先把根节点添加进路径
        track.push_back(root -> val);
        backtrack(root, track, res);
        return res;
    }
    void backtrack(TreeNode* root, vector<int>& track, int& res) {
    
    
        if(root == NULL) return ;
        //叶子节点,则累加
        if(!root -> left && !root -> right) {
    
    
            int sum(0);  //对于每一个叶节点,记录其路径和
            for(int i = 0; i < track.size(); i ++) {
    
    
                sum = sum * 10 + track[i];
            }
            res += sum;
        }
        if(root -> left) {
    
    
            track.push_back(root -> left -> val);
            backtrack(root -> left, track, res);
            track.pop_back();
        }
        if(root -> right) {
    
    
            track.push_back(root -> right -> val);
            backtrack(root -> right, track, res);
            track.pop_back();
        }
    }
};

Idea 3: DFS

  • DFS and backtracking are written very similarly, except that DFS directly brings the updated parameters to the next layer. Backtracking is to update first and then withdraw, but the essence of both is to make choices.
  • DFS is the same as backtracking. When faced with the path and problem of the tree, the root node must be added to the result first.
/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 * };
 */
#include<numeric>
class Solution {
    
    
public:
    int sumNumbers(TreeNode* root) {
    
    
        if(root == NULL) return 0;
        int res = 0; //用于保存最终结果
        int sum = root -> val;  //用于记录每个叶节点的路径和,初始为根节点的值
        dfs(root, res, sum);
        return res;
    }
    void dfs(TreeNode* root, int& res, int sum) {
    
    
        if(root == NULL) return ;
        //如果是叶节点,则累加
        if(!root -> left && !root -> right) {
    
    
            res += sum;
        }
        //两个选择:左子树和右子树
        if(root -> left) {
    
    
            dfs(root -> left, res, sum * 10 + root -> left -> val);
        }
        if(root -> right) {
    
    
            dfs(root -> right, res, sum * 10 + root -> right -> val);
        }
    }
};

Guess you like

Origin blog.csdn.net/cys975900334/article/details/106896402