🧠
Brute Force (Pure Recursion)
💡 Starting with recursion helps understand the natural definition of postorder traversal and builds intuition before optimizing or switching to iterative methods.
Intuition
Postorder traversal means visiting left subtree, then right subtree, then the node itself. Recursion naturally mirrors this definition by calling itself on subtrees before processing the node.
Algorithm
- If the current node is null, return.
- Recursively traverse the left subtree.
- Recursively traverse the right subtree.
- Add the current node's value to the result list.
💡 The recursion stack implicitly remembers where you are, so you don't need to manage your own stack or list of nodes.
from typing import Optional, List
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def postorderTraversal(root: Optional[TreeNode]) -> List[int]:
result = []
def dfs(node):
if not node:
return
dfs(node.left)
dfs(node.right)
result.append(node.val)
dfs(root)
return result
# Example usage:
# root = TreeNode(1, None, TreeNode(2, TreeNode(3)))
# print(postorderTraversal(root)) # Output: [3,2,1]
Line Notes
def postorderTraversal(root: Optional[TreeNode]) -> List[int]:Defines the main function signature for clarity and type safety.
result = []Initialize a list to store the traversal order as we visit nodes.
if not node:Base case to stop recursion when reaching a null child.
result.append(node.val)Add the node's value after visiting left and right subtrees to ensure postorder.
import java.util.*;
class TreeNode {
int val;
TreeNode left, right;
TreeNode(int val) { this.val = val; }
}
public class Solution {
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> result = new ArrayList<>();
dfs(root, result);
return result;
}
private void dfs(TreeNode node, List<Integer> result) {
if (node == null) return;
dfs(node.left, result);
dfs(node.right, result);
result.add(node.val);
}
// Example usage:
// public static void main(String[] args) {
// TreeNode root = new TreeNode(1);
// root.right = new TreeNode(2);
// root.right.left = new TreeNode(3);
// Solution sol = new Solution();
// System.out.println(sol.postorderTraversal(root)); // [3,2,1]
// }
}
Line Notes
public List<Integer> postorderTraversal(TreeNode root)Main method to start traversal and return results.
List<Integer> result = new ArrayList<>();Stores the traversal output in order.
if (node == null) return;Stops recursion at leaf nodes' children.
result.add(node.val);Adds node value after left and right children are processed.
#include <iostream>
#include <vector>
using namespace std;
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
class Solution {
public:
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result;
dfs(root, result);
return result;
}
private:
void dfs(TreeNode* node, vector<int>& result) {
if (!node) return;
dfs(node->left, result);
dfs(node->right, result);
result.push_back(node->val);
}
};
// Example usage:
// int main() {
// TreeNode* root = new TreeNode(1);
// root->right = new TreeNode(2);
// root->right->left = new TreeNode(3);
// Solution sol;
// vector<int> res = sol.postorderTraversal(root);
// for (int v : res) cout << v << ' '; // Output: 3 2 1
// return 0;
// }
Line Notes
vector<int> postorderTraversal(TreeNode* root)Function signature returning vector of node values.
vector<int> result;Stores the postorder traversal result.
if (!node) return;Base case to stop recursion at null nodes.
result.push_back(node->val);Add current node's value after traversing children.
function TreeNode(val, left = null, right = null) {
this.val = val;
this.left = left;
this.right = right;
}
function postorderTraversal(root) {
const result = [];
function dfs(node) {
if (!node) return;
dfs(node.left);
dfs(node.right);
result.push(node.val);
}
dfs(root);
return result;
}
// Example usage:
// const root = new TreeNode(1, null, new TreeNode(2, new TreeNode(3)));
// console.log(postorderTraversal(root)); // [3,2,1]
Line Notes
function postorderTraversal(root)Defines main traversal function accepting root node.
const result = []Array to collect traversal output.
if (!node) return;Stops recursion when node is null.
result.push(node.val)Push node value after left and right subtrees are visited.
Each node is visited once, so time is linear. Space is O(n) due to recursion stack in worst case (skewed tree) and output list.
💡 For a tree with 20 nodes, this means about 20 function calls and storing 20 values, which is efficient for interview constraints.
Interview Verdict: Accepted
This approach is accepted and often the first solution to implement in interviews because it is simple and directly follows the problem definition.