Given the root of a binary tree, can you implement a function to return the inorder traversal of its nodes' values? Let's discuss two approaches: a recursive solution and an iterative solution. For each, explain the time and space complexity. Also, consider edge cases like an empty tree or a tree with a single node. For example, given the tree represented by the array [1,null,2,3]
, your function should return [1,3,2]
. As another example, if the input is [1,2,3,4,5,null,8,null,null,6,7,9]
, the expected output should be [4,2,6,5,7,1,3,9,8]
. And of course, if you get an empty tree []
, the output should also be []
. Finally, what if the input is a single node tree [1]
?
Given the root of a binary tree, return the inorder traversal of its nodes' values.
The most straightforward way to perform an inorder traversal is using recursion. In inorder traversal, we visit the left subtree, then the root, and finally the right subtree.
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def inorder_recursive(root):
if root is None:
return []
return inorder_recursive(root.left) + [root.val] + inorder_recursive(root.right)
An iterative approach uses a stack to simulate the recursive calls. This can be useful for very large trees where recursion might lead to stack overflow errors.
def inorder_iterative(root):
result = []
stack = []
current = root
while current or stack:
if current:
stack.append(current)
current = current.left
else:
current = stack.pop()
result.append(current.val)
current = current.right
return result
Both the recursive and iterative solutions have the same time complexity O(N). The recursive approach has a space complexity of O(H) due to the call stack, while the iterative approach also has a space complexity of O(H) due to the stack. The iterative approach is often preferred for very large trees to avoid potential stack overflow errors associated with deep recursion.