Reference: LeetCode
Difficulty: Medium
Problem
Given a binary tree, return the
preordertraversal of its nodes’ values.
Example:
1 | Input: [1,null,2,3] |
Follow up: Recursive solution is trivial, could you do it iteratively?
Analysis
Recursion
1 | public List<Integer> preorderTraversal(TreeNode root) { |
Time: $O(N)$ since the recursive function is $T(N) = 2T(N/2) + 1$
Space: $O(\log{N})$ (when balanced); $O(N)$ (worst).
Iteration
Note:
- Null check before entering the loop.
- Null check before pushing into the stack, although
Stackdoes allow null elements.ArrayDequedoes not allow null elements. - Push right child first!
1 | // Preorder - Iteration |
Time: $O(N)$
Space: $O(\log{N})$ (when balanced); $O(N)$ (worst).
Morris Traversal
Morris Traversal (reference)
Basic Idea: Morris Traversal uses the idea of threaded binary tree. It uses the left and right pointers of leaves to access the predecessor and successor in a specific traversal.
Step: (p is the current node)
Only one tiny step different from the algorithm in inorder traversal!
- If
p‘s left child isnull, outputpand set its right child as the newp. - Otherwise, then we find the
predecessorofpin the left subtree.- If the
predecessor‘s right child isnull, outputpnode, set its right child top, and updatepwith itsleftchild. - If the
predecessor‘s right child isp, set its right child tonull(restore),and outputand updateppwith itsrightchild.
- If the
- Repeat the steps above until
pisnull.
![]()
1 | public List<Integer> preorderTraversal(TreeNode root) { |
Time: $O(N)$
Intuitively, we may think the time complexity is $O(N\log{N})$ since finding a predecessor of a node takes $O(\log{N})$. In fact, finding all predecessors of all nodes just costs $O(N)$ time because in the whole process each edge/link is only traversed twice, the first time is to locate a node and the second time is to find the predecessor.
Space: $O(1)$