Given the root of a binary tree, return the postorder traversal of its nodes' values. In postorder traversal, you visit the left subtree first, then the right subtree, and finally the root node itself.
root
.The problem asks for a specific order of visiting nodes in a binary tree: left subtree, then right subtree, then the node itself. This is known as postorder traversal. The most straightforward way is to use recursion, as the traversal order naturally fits the recursive structure of trees. However, recursion uses the call stack, which may not be ideal for very deep trees. An iterative approach is also possible, but it requires careful management of the traversal order using a stack.
Initially, one might consider traversing the tree and storing the nodes in the order they are visited. However, to match the postorder requirement, we need to make sure we process the left and right children before the parent node. Recursion handles this naturally, but with iteration, we need to simulate the call stack.
Let's break down the two main approaches to solve this problem:
null
, return immediately.This approach closely follows the definition of postorder traversal. The function calls itself for left and right children, ensuring that the parent node is processed last.
This approach is a bit trickier, as you must carefully manage the order in which nodes are processed. Using two stacks or reversing the result at the end makes sure the output is in postorder.
For both approaches, we traverse each node exactly once, and each node's value is added to the result in the correct order.
Let's use the following binary tree as an example:
1 \ 2 / 3
Step-by-step postorder traversal:
1
.1
is null
, so move to right child 2
.2
, left child is 3
. Traverse left to 3
.3
has no children, so add 3
to the result.2
, right child is null
. Now add 2
to the result.1
, both children are processed. Add 1
to the result.
Final output: [3,2,1]
n
is the number of nodes in the tree.h
is the height of the tree. In the worst case (completely unbalanced tree), h = n
.In this problem, we performed a postorder traversal of a binary tree, visiting each node's left subtree, right subtree, and then the node itself. Both recursive and iterative solutions are efficient and visit each node exactly once. The recursive approach is more intuitive and concise, while the iterative approach avoids recursion and is more explicit about stack usage. Understanding traversal orders and how to implement them both recursively and iteratively is fundamental for working with binary trees.
# Definition for a binary tree node.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class Solution:
def postorderTraversal(self, root):
result = []
def dfs(node):
if not node:
return
dfs(node.left)
dfs(node.right)
result.append(node.val)
dfs(root)
return result
/**
* Definition for a binary tree node.
* 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) {}
* };
*/
class Solution {
public:
void dfs(TreeNode* node, vector<int>& result) {
if (!node) return;
dfs(node->left, result);
dfs(node->right, result);
result.push_back(node->val);
}
vector<int> postorderTraversal(TreeNode* root) {
vector<int> result;
dfs(root, result);
return result;
}
};
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
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);
}
}
/**
* Definition for a binary tree node.
* function TreeNode(val, left, right) {
* this.val = (val===undefined ? 0 : val)
* this.left = (left===undefined ? null : left)
* this.right = (right===undefined ? null : right)
* }
*/
/**
* @param {TreeNode} root
* @return {number[]}
*/
var postorderTraversal = function(root) {
const result = [];
function dfs(node) {
if (!node) return;
dfs(node.left);
dfs(node.right);
result.push(node.val);
}
dfs(root);
return result;
};