/*
         * Find the inorder predecessor of current
         *
         * thought process:
         * start from input node n2,
         * Go to left child first, and then, go the right continuously,
         * until the last one, exclude input node - itself (n1),
         * return the node (n1);
         * Think in a graph of rightmost node in the binary search tree.
         * Also, the code will work if the node is set as right child of
         * its inordre predecessor.
         *
         */
        private static TreeNode findTheInorderPredecessorOfCurrent(TreeNode n2)
        {
            TreeNode n1 = n2.left;      // step 1: moving node (n1), go left first step

            while (n1.right != null && n1.right != n2) // step 2: then, go right continuously;
                // exclude input node itself
                n1 = n1.right;

            return n1;
        }
        /*
         *  previous -> current node
         *  thought process:
         *  if the current node visited has a not-null previous node,
         *  then the two values of nodes should be in increasing order
         *
         * Base test case:
         *   tree only have two nodes, switched;
         *   case A:
         *      2          1
         *     /    ->    /
         *     1         2
         *   case B:
         *     1           2
         *      \    ->     \
         *      2            1
         *  Manually, walk through the code, make sure that v1 and v2 are correct results.
         *
         * input arguments:
         *     n1 -  previous  --
         *     n2 -  current   --
         * output arguments:
         *      v1,       -- viloation node 1
         *      v2,       -- violation node 2
         *      found     -- usually violation can be found at most twice; first violation, set found = true from false.
         *  assumption: n2 node is not null
         *  violation facts:
         *  1. first node, it is the one with bigger value, violated;
         *  but second node, it is the one with smaller value, violated.
         *  2. sometimes, only one violation catch; like base case A, switch two nodes, only two nodes
         *     in the tree. Tree [2,#,1]
         *  3. sometimes, two violationes catch.
         *     Tree [2, 3, 1], inorder traversal result is 3, 2, 1, and then,
         *     first one of viloations is 3, 2, 3>2, the violation one is 3, bigger value;
         *     second one of viloations is 2, 1, 2>1, the violation one is 1, smaller value;
         *     so, 3 and 1 should be swapped back as 1 (2) 3
         */
        private static void violationChecking(TreeNode n1,
                                              TreeNode n2,
                                              ref TreeNode v1,
                                              ref TreeNode v2,
                                              ref bool found)
        {
            if (n1 != null && n1.val > n2.val)  // break "increasing order" principle
            {
                if (!found)
                {
                    v1 = n1;   // bigger value violated - first one always
                    found = true;
                }

                v2 = n2;       // smaller value violated - second one always
            }
        }
        /*
         * Problem: Leetcode 99 - recover binary search tree
         * Reference:
         * https://github.com/jianminchen/Leetcode_C-/blob/master/99RecoverBinarySearchTree.cs
         *
         * julia's comment:
         * 1. Extract two functions:
         *    findTheInorderPredecessorOfCurrent
         *    violationChecking
         *
         * 2. Add test cases for those two functions,
         *    make them memorizable, testable, maintainable
         *
         * 3. online judge passes
         *  1916 / 1916 test cases passed.
            Status: Accepted
            Runtime: 324 ms
         *
         * 4. Read the code, and write down the script:
         * Actually it is in Morris order traversal, not using stack; use the existing right
         * child pointer connect the traversal nodes, later revert the change.
         *
         * First, use two violation nodes, 3 nodes: current node, previous node, parent node to help
         * tracking the inorder traversal process.
         *
         * base case discussion: root node is null, return
         * start from root node, get in a loop,
         *
         * if node in the loop (ith)'s left child is null, then,
         * do a violation checking function call using parent node (pa), ith node input arguments,
         * after the call, recover phase: ith node is set as pa node, ith.right is ith node (go to its right child).
         * using example to explain:
         *     1
         *      \
         *       3
         *      / \
         *      2  4
         *    starting from root node (1), (1)'s left child is empty, and then, before moving to next node:
         *    (1)'s right child (3), do violation check, and then, set ith's node to (3), and parent node as ith's node (1).
         *
         * else if ith's left child is not null, then,
         * find predecessor node  of ith's node, denoted as previous node (pr),
         * if pr's right child is null, then, threaded link is not set up,
         * so, set up the link before moving to ith's node's next one - its left child;
         * else if pr's right child is not null, then,
         *     break the threaded link;
         *     do violation check, two node, pa, ith;
         *     recover phase, set parent node pa = ith, and then, move to ith's right node.
         *
         * using example to explain the work here:
         *       4
         *      /
         *     2
         *    / \
         *    1  3
         *    starting from root node (4), (4)'s left child is not null, and then, find its inorder
         *    predecessor node (3),
         *     case A: node (3)'s right child is not set up to node (4), then,
         *     set up node (3)'s right = node (4), move ith's node's left node, node (2).
         *
         *     case B: node (3)'s right child is already set up to node (4), then
         *     revert the change, (3).right = null
         *     do violation check, parent node pa, ith node,
         *     recover phase: set parent node pa as ith node, and then, move to ith's right node.
         *
         *     What we miss here, Morris order second visit of node 4. how to do traversal?
         *     visit (4), then, set up (3)'s right = (4), so, continue to travel, 4->2.
         *     output of inorder traversal only happens two cases:
         *       one is to travel fake link, right child; second one is to travel to its right child.
         *
         *
         *
         */
        public static void recoverTree(TreeNode root)
        {
            TreeNode v1 = null,     // two vilation nodes, v1 and v2
                     v2 = null;

            TreeNode ith,           // ith - current node, node will go through inorder traversal
                     pr,            // pr - previous node
                     pa = null;     // pa - parent node

            if (root == null)
                return;

            bool found = false;

            ith = root;       // start from root node r
            // pa = null, and pr = null

            while (ith != null)    // need to get into the inorder traversal without a stack - O(n) space
            {
                if (ith.left == null)
                {
                    violationChecking(pa, ith, ref v1, ref v2, ref found);

                    pa = ith;         // recover phase, go to next node;
                                      // no left, then, go to the right.
                    ith = ith.right;
                }
                else
                {
                    /* Find the inorder predecessor of current */
                    pr = findTheInorderPredecessorOfCurrent(ith);

                    /* Make current as right child of its inorder predecessor */
                    if (pr.right == null)
                    {
                        pr.right = ith;
                        ith = ith.left;  // go to next iteration, left child.
                    }

                    /* Revert the changes made in if part to restore the original
                    tree i.e., fix the right child of predecssor */
                    else
                    {
                        pr.right = null;   // revert the change. Why? Remember?

                        violationChecking(pa, ith, ref v1, ref v2, ref found);

                        pa = ith;
                        ith = ith.right;    // go to next iteration, no left child, so right child.
                    } /* End of if condition pre->right == NULL */
                }     /* End of if condition current->left == NULL*/
            }         /* End of while */

            if (v1 != null && v2 != null)  // swap v1 and v2
            {
                int tmp = v1.val;
                v1.val = v2.val;
                v2.val = tmp;
            }
        }