Problem Statement
Traverse a binary tree (inorder/postorder/preorder), using O(1) space, return root of tree
Definition Threaded Tree
A binary tree is threaded by making all right child pointers that would normally be null point to the inorder successor of the node (if it exists), and all left child pointers that would normally be null point to the inorder predecessor of the node.
Pattern: Related: Find median of BST in O(n) time and O(1) space - GeeksforGeeks
Inorder Traversal
Binary Tree Inorder Traversal - LeetCode
Pseudo Code
1. Initialize current as root
2. While current is not NULL
If current hs a left child
ifa) Make current as right child of the 'rightmost
node in current's left subtree' or its 'inorder predecessor'
ifb) Go to left child, i.e., current = current->left
Else
ea) Print current’s data
eb) Go to the right, i.e., current = current->right
Java Code
public ArrayList<Integer> inorder (TreeNode root){
TreeNode curr = root;
ArrayList<Integer> res = new ArrayList<>();
while(curr != null) {
if(curr.left != null) {
// get inorder predecessor 'pred'
TreeNode pred = curr.left;
while(pred.right != null && pred.right != curr) pred = pred.right;
if(pred.right == null) { // pred not connected to root/curr
pred.right = curr; // connect pred to root/curr
curr = curr.left;
} else { // pred.right == curr (pred already connected to root/curr)
pred.right = null; // disconnect
res.add(curr.data); // print
curr = curr.right; // traverse right subtree - inorder successor
}
} else { // curr.left -> null
res.add(curr.data); // print
curr = curr.right; // traverse right subtree
}
}
return res;
}
- print
- the second time you arrive at root
pred.right != null
because ofLNR
- when
curr.left == null
- the second time you arrive at root
Preorder Traversal
Binary Tree Preorder Traversal - LeetCode
Java Code
public List<Integer> preorderTraversal (TreeNode root){
TreeNode curr = root;
ArrayList<Integer> res = new ArrayList<>();
while(curr != null) {
if(curr.left != null) {
// get inorder predecessor 'pred'
TreeNode pred = curr.left;
while(pred.right != null && pred.right != curr) pred = pred.right;
if(pred.right == null) { // pred not connected to root/curr
pred.right = curr; // connect pred to root/curr
res.add(curr.val); // print
curr = curr.left;
} else { // pred.right == curr (pred already connected to root/curr)
pred.right = null; // disconnect
curr = curr.right; // traverse right subtree - inorder successor
}
} else { // curr.left -> null
res.add(curr.val); // print
curr = curr.right; // traverse right subtree
}
}
return res;
}
- print
- the first time curr is at the root node, not the second (i.e. when
pred.right == curr
, that meanscurr
has been visited before) - and when
curr.left == null
- the first time curr is at the root node, not the second (i.e. when
PostOrder Traversal
// right first preorder, in reverse = postorder
public List<Integer> postorder (TreeNode root){
TreeNode curr = root;
ArrayList<Integer> res = new ArrayList<>();
while(curr != null) {
if(curr.right != null) {
// get inorder successor 'pred'
TreeNode pred = curr.right;
while(pred.left != null && pred.left != curr) pred = pred.left;
if(pred.left == null) { // pred not connected to root/curr
pred.left = curr; // connect pred to root/curr
res.add(curr.val); // print
curr = curr.right;
} else { // pred.left == curr (pred already connected to root/curr)
pred.left = null; // disconnect
curr = curr.left; // traverse left subtree - inorder predecessor
}
} else { // curr.right -> null
res.add(curr.val); // print
curr = curr.left; // traverse left subtree
}
}
Collections.reverse(res);
return res;
}
- right first preorder, in reverse = postorder
- traverse right subtree first
- print root/curr on first traversal like you do in preorder
- connect root’s inorder successor
succ
to root on firs traversal - disconnect it on second traversal, and traverse
curr's
left subtree