Binary Tree Preorder Traversal easy
Problem Statement
Given the root
of a binary tree, return the preorder traversal of its nodes' values.
Example 1
Input: root = [1,null,2,3] Output: [1,2,3]
Example 2
Input: root = [] Output: []
Steps
The preorder traversal of a binary tree follows the order: Root -> Left -> Right. We'll implement this using a recursive approach and then an iterative approach using a stack.
Recursive Approach:
- Base Case: If the root is None (empty tree), return an empty list.
- Recursive Step:
- Add the root's value to the result list.
- Recursively traverse the left subtree and append the result to the list.
- Recursively traverse the right subtree and append the result to the list.
Iterative Approach:
- Initialize an empty stack and an empty result list.
- Push the root node onto the stack.
- While the stack is not empty:
- Pop a node from the stack.
- Add the node's value to the result list.
- Push the right child (if it exists) onto the stack.
- Push the left child (if it exists) onto the stack (important: left child first for correct order).
Explanation
Recursive Approach: The recursive approach directly mirrors the definition of preorder traversal. It's concise but might lead to stack overflow errors for very deep trees.
Iterative Approach: The iterative approach avoids recursion by using a stack to simulate the function call stack. This makes it more memory-efficient for deep trees, avoiding potential stack overflow issues. The order of pushing the right and left children onto the stack is crucial to maintain the correct preorder traversal.
Code
# 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 preorderTraversal(self, root: TreeNode) -> list[int]:
#Recursive Approach
result = []
def traverse(node):
if not node:
return
result.append(node.val)
traverse(node.left)
traverse(node.right)
traverse(root)
return result
#Iterative Approach (more efficient for very deep trees)
# result = []
# stack = [root]
# while stack:
# node = stack.pop()
# if node:
# result.append(node.val)
# stack.append(node.right)
# stack.append(node.left)
# return result
Complexity
Recursive Approach:
- Time Complexity: O(N), where N is the number of nodes in the tree. We visit each node once.
- Space Complexity: O(H), where H is the height of the tree. This is due to the recursive call stack. In the worst case (a skewed tree), H could be N.
Iterative Approach:
- Time Complexity: O(N), where N is the number of nodes in the tree. We visit each node once.
- Space Complexity: O(W), where W is the maximum width of the tree. In the worst case (a complete binary tree), W could be N. However, it's generally better than the recursive approach's space complexity for deep trees.