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) {} }; |
In case those last three lines look a little confusing to you, those are three constructors: You can construct a tree node with a value of 0 and no children, a tree node with a given value and no children, or a tree node with a given value and given children.
Your job is to write the method sumNumbers in the class Solution, with the following prototype:
class Solution { public: int sumNumbers(TreeNode *root); }; |
Here's a description of the tree and what sumNumbers() should produce:
5 / \ / \ 3 6 Answer = 53 + 56 = 109. |
2 / \ / \ 3 4 / \ / \ 1 0 Answer = 23 + 241 + 240 = 504 |
2 / \ / \ 4 3 / \ / \ 1 0 Answer = 241 + 240 + 23 = 504 |
UNIX> cat example-1.txt 5 3 6 UNIX> cat example-2.txt 2 3 4 -1 -1 1 0 # We need two -1's to take the place of the two children of node 3. UNIX> cat example-3.txt 2 4 3 1 0 # Formatting doesn't matter UNIX>I'm not going to go over the code, but you should take a read if you're interested. I have bigger example files in the other example-x.txt files:
UNIX> wc example-*.txt 2 3 6 example-1.txt 3 7 16 example-2.txt 1 5 10 example-3.txt 20 20 40 example-4.txt 1 31 79 example-5.txt 1 63 136 example-6.txt 1 250 534 example-7.txt 1 500 1249 example-8.txt 1 1000 2295 example-9.txt 31 1879 4365 total UNIX>
/* We're not going to solve the problem. Instead, we're going to simply print out each node and the vals of its two children (-1 if the child is nullptr). */ int Solution::sumNumbers(TreeNode *root) { printf("Node: %d Left: %d Right: %d\n", root->val, (root->left == nullptr) ? -1 : root->left->val, (root->right == nullptr) ? -1 : root->right->val); if (root->left != nullptr) (void) sumNumbers(root->left); if (root->right != nullptr) (void) sumNumbers(root->right); return 0; } |
We run this on our examples above, and on example-9.txt to confirm that it's reading the trees correctly, and to show that example-9.txt has 706 nodes:
UNIX> g++ Print-Nodes.cpp UNIX> a.out < example-1.txt Node: 5 Left: 3 Right: 6 Node: 3 Left: -1 Right: -1 Node: 6 Left: -1 Right: -1 0 UNIX> a.out < example-2.txt Node: 2 Left: 3 Right: 4 Node: 3 Left: -1 Right: -1 Node: 4 Left: 1 Right: 0 Node: 1 Left: -1 Right: -1 Node: 0 Left: -1 Right: -1 0 UNIX> a.out < example-3.txt Node: 2 Left: 4 Right: 3 Node: 4 Left: 1 Right: 0 Node: 1 Left: -1 Right: -1 Node: 0 Left: -1 Right: -1 Node: 3 Left: -1 Right: -1 0 UNIX> a.out < example-9.txt | wc # This shows that there are 706 nodes in the example (the last line, which is a zero, doesn't correspond to a node). 707 4237 21889 UNIX>Answer the following question to yourself: Is this a preorder or a postorder traversal? The answer is preorder, because we print before we do the recursion.
5 / \ / \ 53 56 |
2 / \ / \ 23 24 / \ / \ 241 240 |
2 / \ / \ 24 23 / \ / \ 241 240 |
Can you see a pattern? Each number is equal to its parent's number times ten, plus its val. So we can do a preorder traversal, where we define the following method:
int Preorder(TreeNode *n, int parent_number); |
The code in sumNumbers simply calls this with the root and zero:
int Solution::sumNumbers(TreeNode *root) { return Preorder(root, 0); } |
And here's the code for Preorder():
/* Here's the preorder traversal. Calculate the node's number, and then either return it (if you have no children). Or sum the values of your children. */ int Solution::Preorder(TreeNode *n, int parent_number) { int number, rv; /* Calculate the number and return it if you are a leaf node. */ number = parent_number * 10 + n->val; if (n->left == nullptr && n->right == nullptr) return number; /* Otherwise, sum the numbers of your children and return that. */ rv = 0; if (n->left != nullptr) rv += Preorder(n->left, number); if (n->right != nullptr) rv += Preorder(n->right, number); return rv; } |