🧠
Iterative Postorder Traversal with Stack
💡 This approach uses an explicit stack to simulate postorder traversal iteratively, useful if recursion is limited or to demonstrate mastery of tree traversal techniques.
Intuition
Use a stack to traverse the tree postorder, computing heights bottom-up and storing them in a map, checking balance as we go.
Algorithm
- Use a stack to traverse nodes in postorder iteratively.
- Maintain a map/dictionary to store heights of visited nodes.
- For each node, after visiting children, compute height and check balance.
- If imbalance detected, return false immediately.
- If traversal completes without imbalance, return true.
💡 This approach is more complex but avoids recursion stack limits and shows control over traversal order.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def isBalanced(root):
if not root:
return True
stack = []
node = root
last_visited = None
heights = {}
while stack or node:
if node:
stack.append(node)
node = node.left
else:
peek = stack[-1]
if peek.right and last_visited != peek.right:
node = peek.right
else:
left_height = heights.get(peek.left, 0)
right_height = heights.get(peek.right, 0)
if abs(left_height - right_height) > 1:
return False
heights[peek] = 1 + max(left_height, right_height)
last_visited = stack.pop()
return True
# Example usage:
if __name__ == '__main__':
root = TreeNode(3)
root.left = TreeNode(9)
root.right = TreeNode(20, TreeNode(15), TreeNode(7))
print(isBalanced(root)) # Expected: True
Line Notes
stack = []Stack to simulate recursion for iterative traversal
while stack or node:Continue until all nodes are processed
if node: stack.append(node)Traverse left subtree as far as possible
if abs(left_height - right_height) > 1:Check balance condition at current node using stored heights
import java.util.*;
class TreeNode {
int val;
TreeNode left, right;
TreeNode(int val) { this.val = val; }
}
public class Solution {
public boolean isBalanced(TreeNode root) {
if (root == null) return true;
Deque<TreeNode> stack = new ArrayDeque<>();
Map<TreeNode, Integer> heights = new HashMap<>();
TreeNode node = root, lastVisited = null;
while (!stack.isEmpty() || node != null) {
if (node != null) {
stack.push(node);
node = node.left;
} else {
TreeNode peek = stack.peek();
if (peek.right != null && lastVisited != peek.right) {
node = peek.right;
} else {
int leftHeight = heights.getOrDefault(peek.left, 0);
int rightHeight = heights.getOrDefault(peek.right, 0);
if (Math.abs(leftHeight - rightHeight) > 1) return false;
heights.put(peek, 1 + Math.max(leftHeight, rightHeight));
lastVisited = stack.pop();
}
}
}
return true;
}
public static void main(String[] args) {
Solution sol = new Solution();
TreeNode root = new TreeNode(3);
root.left = new TreeNode(9);
root.right = new TreeNode(20);
root.right.left = new TreeNode(15);
root.right.right = new TreeNode(7);
System.out.println(sol.isBalanced(root)); // true
}
}
Line Notes
Deque<TreeNode> stack = new ArrayDeque<>();Stack to simulate recursion for iterative traversal
while (!stack.isEmpty() || node != null) {Traverse until all nodes are processed
if (peek.right != null && lastVisited != peek.right) {Traverse right subtree if not yet visited
if (Math.abs(leftHeight - rightHeight) > 1) return false;Check balance condition at current node
#include <iostream>
#include <stack>
#include <unordered_map>
#include <algorithm>
using namespace std;
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
bool isBalanced(TreeNode* root) {
if (!root) return true;
stack<TreeNode*> stk;
unordered_map<TreeNode*, int> heights;
TreeNode* node = root;
TreeNode* lastVisited = nullptr;
while (!stk.empty() || node) {
if (node) {
stk.push(node);
node = node->left;
} else {
TreeNode* peek = stk.top();
if (peek->right && lastVisited != peek->right) {
node = peek->right;
} else {
int leftHeight = heights.count(peek->left) ? heights[peek->left] : 0;
int rightHeight = heights.count(peek->right) ? heights[peek->right] : 0;
if (abs(leftHeight - rightHeight) > 1) return false;
heights[peek] = 1 + max(leftHeight, rightHeight);
lastVisited = peek;
stk.pop();
}
}
}
return true;
}
int main() {
TreeNode* root = new TreeNode(3);
root->left = new TreeNode(9);
root->right = new TreeNode(20);
root->right->left = new TreeNode(15);
root->right->right = new TreeNode(7);
cout << (isBalanced(root) ? "true" : "false") << endl; // true
return 0;
}
Line Notes
stack<TreeNode*> stk;Stack to simulate recursion for iterative traversal
while (!stk.empty() || node) {Traverse until all nodes are processed
if (peek->right && lastVisited != peek->right) {Traverse right subtree if not yet visited
if (abs(leftHeight - rightHeight) > 1) return false;Check balance condition at current node
function TreeNode(val, left=null, right=null) {
this.val = val;
this.left = left;
this.right = right;
}
function isBalanced(root) {
if (!root) return true;
const stack = [];
const heights = new Map();
let node = root;
let lastVisited = null;
while (stack.length > 0 || node !== null) {
if (node !== null) {
stack.push(node);
node = node.left;
} else {
const peek = stack[stack.length - 1];
if (peek.right !== null && lastVisited !== peek.right) {
node = peek.right;
} else {
const leftHeight = heights.get(peek.left) || 0;
const rightHeight = heights.get(peek.right) || 0;
if (Math.abs(leftHeight - rightHeight) > 1) return false;
heights.set(peek, 1 + Math.max(leftHeight, rightHeight));
lastVisited = stack.pop();
}
}
}
return true;
}
// Example usage:
const root = new TreeNode(3, new TreeNode(9), new TreeNode(20, new TreeNode(15), new TreeNode(7)));
console.log(isBalanced(root)); // true
Line Notes
const stack = [];Stack to simulate recursion for iterative traversal
while (stack.length > 0 || node !== null) {Traverse until all nodes are processed
if (peek.right !== null && lastVisited !== peek.right) {Traverse right subtree if not yet visited
if (Math.abs(leftHeight - rightHeight) > 1) return false;Check balance condition at current node
Each node is visited once, and heights stored in a map. Stack space is O(h) where h is tree height.
💡 For n=20 nodes, this is efficient and avoids recursion stack overflow.
Interview Verdict: Accepted
This approach is less common but useful when recursion is restricted or to demonstrate iterative traversal skills.