/**
* Two elements of a binary search tree (BST) are swapped by mistake.
*
* Recover the tree without changing its structure.
*
* Note:
* A solution using O(n) space is pretty straight forward. Could you devise a
* constant space solution?
*
* Tags: Tree, DFS
*/
class RecoverBST {
public static void main(String[] args) {
}
TreeNode prev;
TreeNode first;
TreeNode second;
/**
* Do morris traversal to find those swapped nodes
*/
public void recoverTree(TreeNode root) {
if (root == null) return;
prev = new TreeNode(Integer.MIN_VALUE);
morrisInorder(root);
// swap values of first and second
int t = first.val;
first.val = second.val;
second.val = t;
}
/**
* Morris Traversal, link null left node to its inorder predecessor
* link null right node to its inorder successor
* Initialize current as root
* While current is not NULL
* If current does not have left child
* a) Print current’s data
* b) Go to the right, i.e., current = current->right
* Else
* a) Make current as right child of the rightmost node in current's left
* subtree
* b) Go to this left child, i.e., current = current->left
*/
void morrisInorder(TreeNode root) {
TreeNode cur = root;
TreeNode pred = null;
while (cur != null) {
if (cur.left == null) {
// set first and second if first still doesn't exist
if (cur.val <= prev.val && first == null) first = prev;
// set second only if first exists
if (cur.val <= prev.val && first != null) second = cur;
prev = cur; // note that previous node needs to be saved
cur = cur.right; // move to next node
} else {
pred = cur.left;
while (pred.right != null && pred.right != cur) pred = pred.right;
if (pred.right == null) { // not connected
pred.right = cur; // connect predecessor to current node
cur = cur.left; // move to left child
} else { // connected
if (cur.val <= prev.val && first == null) first = prev;
if (cur.val <= prev.val && first != null) second = cur;
pred.right = null; // break connection
prev = cur; // previous node needs to be saved
cur = cur.right; // move to right child
}
}
}
}
public class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
}