Given the root
of a binary tree, return the postorder traversal of its nodes' values.
Example 1:
Input: root = [1,null,2,3]
Output: [3,2,1]
Explanation: Consider a binary tree where the root is 1, the left child is null, the right child is 2, and the left child of 2 is 3. The postorder traversal would be [3, 2, 1].
Example 2:
Input: root = [1,2,3,4,5,null,8,null,null,6,7,9]
Output: [4,6,7,5,2,9,8,3,1]
Constraints:
[0, 100]
.-100 <= Node.val <= 100
Could you implement both a recursive and an iterative solution? Also, how would you analyze the time and space complexity of each approach?
## Postorder Traversal of a Binary Tree
This problem asks us to implement a postorder traversal of a binary tree. Postorder traversal visits the left subtree, then the right subtree, and finally the root node itself.
### 1. Recursive Solution
The recursive solution is the most straightforward way to implement postorder traversal. We recursively call the function on the left and right subtrees before processing the current node.
```python
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def postorder_recursive(root):
if root is None:
return []
left_subtree = postorder_recursive(root.left)
right_subtree = postorder_recursive(root.right)
return left_subtree + right_subtree + [root.val]
# Example usage:
root = TreeNode(1, None, TreeNode(2, TreeNode(3)))
print(postorder_recursive(root))
An iterative solution can be implemented using a stack. The key idea is to simulate the call stack of the recursive approach.
def postorder_iterative(root):
if root is None:
return []
stack = [root]
visited = set()
result = []
while stack:
node = stack[-1]
if node.left and node.left not in visited:
stack.append(node.left)
elif node.right and node.right not in visited:
stack.append(node.right)
else:
result.append(node.val)
visited.add(node)
stack.pop()
return result
# Example usage:
root = TreeNode(1, None, TreeNode(2, TreeNode(3)))
print(postorder_iterative(root))
Morris traversal is an in-order traversal algorithm that does not use recursion or a stack. This makes it an optimal solution in terms of space complexity for certain traversals, and can be adapted for postorder traversal as well.
def reverse_linked_list(start, end):
prev = None
curr = start
while curr != end:
next_node = curr.right
curr.right = prev
prev = curr
curr = next_node
return prev
def postorder_morris(root):
result = []
dummy = TreeNode(0)
dummy.left = root
current = dummy
while current:
if current.left is None:
current = current.right
else:
predecessor = current.left
while predecessor.right and predecessor.right != current:
predecessor = predecessor.right
if predecessor.right is None:
predecessor.right = current
current = current.left
else:
predecessor.right = None
temp = current.left
tail = reverse_linked_list(temp, current)
node = tail
while node:
result.append(node.val)
node = node.right
reverse_linked_list(tail, temp)
current = current.right
return result
root = TreeNode(1, None, TreeNode(2, TreeNode(3)))
print(postorder_morris(root))
None
, the function should return an empty list. Both the recursive and iterative solutions handle this case correctly.