Morris Traversal Inorder Without Stack in DSA Java - Time & Space Complexity
We want to understand how the Morris Traversal method for inorder tree traversal performs as the tree grows.
Specifically, how the number of steps changes when the tree has more nodes.
Analyze the time complexity of the following Morris Inorder Traversal code.
public void morrisInorder(TreeNode root) {
TreeNode current = root;
while (current != null) {
if (current.left == null) {
System.out.print(current.val + " ");
current = current.right;
} else {
TreeNode predecessor = current.left;
while (predecessor.right != null && predecessor.right != current) {
predecessor = predecessor.right;
}
if (predecessor.right == null) {
predecessor.right = current;
current = current.left;
} else {
predecessor.right = null;
System.out.print(current.val + " ");
current = current.right;
}
}
}
}
This code traverses a binary tree inorder without using extra stack or recursion by temporarily modifying pointers.
Look at the loops and repeated steps:
- Primary operation: Moving through nodes and finding the rightmost child (predecessor) in the left subtree.
- How many times: Each edge in the tree is visited at most twice: once to create a temporary link and once to remove it.
As the number of nodes (n) increases, each node is visited a limited number of times.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 20 visits (each edge twice) |
| 100 | About 200 visits |
| 1000 | About 2000 visits |
Pattern observation: The operations grow roughly linearly with the number of nodes.
Time Complexity: O(n)
This means the traversal time grows directly in proportion to the number of nodes in the tree.
[X] Wrong: "Since there is a nested while loop, the time complexity must be O(n²)."
[OK] Correct: The inner loop moves along edges that are only visited twice total, so the total work is still proportional to n, not n squared.
Understanding Morris Traversal shows you can traverse trees efficiently without extra memory, a skill that impresses by showing deep knowledge of tree algorithms.
"What if we used recursion instead of Morris Traversal? How would the time and space complexity change?"
Practice
Solution
Step 1: Understand Morris Traversal space usage
Morris Traversal modifies tree links temporarily to avoid using stack or recursion, so it uses O(1) extra space.Step 2: Compare with traditional methods
Traditional inorder traversal uses recursion or stack which require O(h) space, where h is tree height.Final Answer:
It uses no extra space for stack or recursion -> Option DQuick Check:
Space complexity = O(1) [OK]
- Thinking Morris is faster in time complexity
- Assuming it only works on BSTs
- Believing it requires balanced trees
Solution
Step 1: Identify the thread link direction
In Morris Traversal, the right child of the inorder predecessor is linked to current node to create a thread.Step 2: Match with code snippet
The correct assignment is predecessor.right = current; to create the temporary link.Final Answer:
predecessor.right = current; -> Option CQuick Check:
Thread link = predecessor.right = current [OK]
- Assigning current.left to predecessor instead
- Using predecessor.left instead of right
- Confusing current.right with predecessor.right
2 / \ 1 3
Solution
Step 1: Perform inorder traversal manually
Inorder traversal visits left subtree, root, then right subtree. For this tree: left=1, root=2, right=3.Step 2: List nodes in inorder
Nodes visited in order: 1, 2, 3.Final Answer:
[1, 2, 3] -> Option AQuick Check:
Inorder = left-root-right = [1, 2, 3] [OK]
- Confusing preorder or postorder with inorder
- Mixing up left and right child order
- Assuming Morris changes traversal order
while (current != null) {
if (current.left == null) {
System.out.print(current.val + " ");
current = current.right;
} else {
TreeNode predecessor = current.left;
while (predecessor.right != null) {
predecessor = predecessor.right;
}
predecessor.right = current;
current = current.left;
}
}
What is the main bug causing an infinite loop?Solution
Step 1: Identify missing condition in inner loop
The inner while loop should stop if predecessor.right == current to avoid infinite loop.Step 2: Explain infinite loop cause
Without checking predecessor.right == current, the loop never breaks and keeps moving right, causing infinite loop.Final Answer:
Not checking if predecessor.right == current before linking -> Option BQuick Check:
Check predecessor.right == current to break loop [OK]
- Ignoring thread existence check
- Assuming printing happens in else block
- Incorrect predecessor initialization
Solution
Step 1: Understand Morris Traversal threading
For nodes with left children, Morris Traversal finds the rightmost node in left subtree and links its right pointer to current node temporarily.Step 2: Explain handling of left-only nodes
This threading allows traversal to return to current node after left subtree is processed, enabling inorder traversal without stack or recursion.Final Answer:
It creates temporary right links from the rightmost node of left subtree back to current node -> Option AQuick Check:
Threading rightmost left subtree node to current [OK]
- Thinking recursion is used internally
- Assuming nodes are skipped
- Believing tree is converted to linked list
Ready to prove it?
Pass the test and this pattern moves unknown
