Given a binary tree, return the postorder traversal of its nodes' values.
Example:
Input:[1,null,2,3]
1 \ 2 / 3 Output:[3,2,1]
Follow up: Recursive solution is trivial, could you do it iteratively?
The core challenge of this problem is to perform a postorder traversal of a binary tree. In postorder traversal, we visit the left subtree, then the right subtree, and finally the root node. This traversal is significant in various applications such as expression tree evaluations and syntax tree traversals.
Potential pitfalls include misunderstanding the traversal order and handling null nodes incorrectly.
To solve this problem, we can consider both recursive and iterative approaches:
The recursive approach is straightforward but not optimal for large trees due to potential stack overflow issues. Here is a simple recursive solution:
// Recursive Postorder Traversal
void postorderTraversal(TreeNode* root, vector<int>& result) {
if (root == nullptr) return;
postorderTraversal(root->left, result);
postorderTraversal(root->right, result);
result.push_back(root->val);
}
While this solution is easy to implement, it is not suitable for the follow-up requirement of an iterative solution.
To achieve an iterative solution, we can use two stacks. The first stack is used to traverse the tree, and the second stack is used to store the nodes in postorder. Here is the detailed algorithm:
stack1
and stack2
.stack1
.stack1
is not empty:
stack1
and push it to stack2
.stack1
.stack2
and add their values to the result list.Here is a step-by-step breakdown of the iterative algorithm:
// Iterative Postorder Traversal
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result;
if (root == nullptr) return result;
stack<TreeNode*> stack1, stack2;
stack1.push(root);
while (!stack1.empty()) {
TreeNode* node = stack1.top();
stack1.pop();
stack2.push(node);
if (node->left) stack1.push(node->left);
if (node->right) stack1.push(node->right);
}
while (!stack2.empty()) {
result.push_back(stack2.top()->val);
stack2.pop();
}
return result;
}
Below is the complete C++ code for the iterative postorder traversal:
#include <iostream>
#include <vector>
#include <stack>
using namespace std;
// Definition for a binary tree node.
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result;
if (root == nullptr) return result;
stack<TreeNode*> stack1, stack2;
stack1.push(root);
while (!stack1.empty()) {
TreeNode* node = stack1.top();
stack1.pop();
stack2.push(node);
if (node->left) stack1.push(node->left);
if (node->right) stack1.push(node->right);
}
while (!stack2.empty()) {
result.push_back(stack2.top()->val);
stack2.pop();
}
return result;
}
// Helper function to create a new tree node
TreeNode* newNode(int data) {
TreeNode* node = new TreeNode(data);
node->left = node->right = nullptr;
return node;
}
// Main function to test the postorder traversal
int main() {
TreeNode* root = newNode(1);
root->right = newNode(2);
root->right->left = newNode(3);
vector<int> result = postorderTraversal(root);
for (int val : result) {
cout << val << " ";
}
return 0;
}
The time complexity of the iterative approach is O(n)
, where n
is the number of nodes in the tree. This is because each node is processed exactly twice. The space complexity is also O(n)
due to the use of two stacks.
Consider the following edge cases:
Each of these cases should be handled correctly by the algorithm.
To test the solution comprehensively, consider the following test cases:
Use a variety of test cases to ensure the algorithm works correctly in all scenarios.
When approaching such problems, consider the following tips:
In this blog post, we discussed the problem of postorder tree traversal and provided both recursive and iterative solutions. We analyzed the complexity and discussed edge cases and testing strategies. Understanding and solving such problems is crucial for improving problem-solving skills and preparing for technical interviews.
For further reading and practice, consider the following resources: