The intuition for inverting a binary tree is to swap the left and right children of each node recursively or iteratively. We can visualize this as flipping the tree horizontally, where each node’s left child becomes its right child and vice versa. The key part for me, which may seem obvious, was realising that a binary tree is a data structure where each node has at most two child nodes.
Recursive Approach
Initially solved with a recursive approach based on the above intuition:
1. Start with the root node and define the base cases.
1. If the root is None (empty tree), return None.
2. If the root does not have 2 children, it is a leaf node -> return the root as is.
2. For non-leaf nodes, recursively invert the left and right subtrees.
3. Swap the inverted left and right subtrees.
4. Return the root of the inverted tree.
Complexity
Time complexity: O(n)
We visit each node in the tree exactly once, where n is the number of nodes in the tree. Therefore, the time complexity is linear.
Space complexity: O(h)
The space complexity is O(h), where h is the height of the tree. This is due to the recursive call stack. In the worst case (a completely unbalanced tree), this could be O(n), but for a balanced tree, it would be O(\log n).
For an interative appraoch, a stack or queue works nicely as we can do the following:
1. Start with the root node and push it onto the stack
2. Take a node from the stack
3. Swap the left and right children
4. Add the non-None children to the stack for processing
Complexity
Time complexity: O(n)
We visit each node in the tree exactly once, where n is the number of nodes in the tree, performing a constant time operation (swapping the nodes), and the while loop runs n times. Therefore, the time complexity is linear.
Space complexity: O(n)
This occurs in a “perfect” binary tree, where the last level is completely full.
At its maximum, the queue could contain all the leaf nodes, which in a perfect binary tree is (n+1)/2 nodes (slightly more than half of all nodes).
For a balanced tree, it could be O(w), where w is the maximum width of the tree (which is typically O(\log n) for a balanced tree).
For a skewed tree (e.g. a linked list), it would be O(1) as we’d only ever have one node in the queue at a time.