面试中的二叉树问题总结【Java版】

面试中的二叉树问题总结【Java版】

3718人阅读 评论(0) 收藏 举报
本文章已收录于:
分类:
数据结构(6)
作者同类文章 X
  • 二叉树的常见问题及其解决程序
  • hash_set哈希集合容器
  • list和vector有什么区别?
  • 经典面试题:设计包含min函数的栈,O(1)空间实现方法
  • 更多
算法(18)
作者同类文章 X
[java] view plain copy
print ?
  1. package Algorithms.tree;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.Iterator;  
  5. import java.util.LinkedList;  
  6. import java.util.List;  
  7. import java.util.Queue;  
  8. import java.util.Stack;  
  9.   
  10.   
  11. /** 
  12.  * REFS:   
  13.  * http://blog.csdn.net/fightforyourdream/article/details/16843303 面试大总结之二:Java搞定面试中的二叉树题目 
  14.  * http://blog.csdn.net/luckyxiaoqiang/article/details/7518888          轻松搞定面试中的二叉树题目  
  15.  * http://www.cnblogs.com/Jax/archive/2009/12/28/1633691.html           算法大全(3) 二叉树  
  16.  *   
  17.  * 1. 求二叉树中的节点个数: getNodeNumRec(递归),getNodeNum(迭代)  
  18.  * 2. 求二叉树的深度: getDepthRec(递归),getDepth   
  19.  * 3. 前序遍历,中序遍历,后序遍历: preorderTraversalRec, preorderTraversal, inorderTraversalRec, postorderTraversalRec  
  20.  * (https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_2)  
  21.  * 4.分层遍历二叉树(按层次从上往下,从左往右): levelTraversal, levelTraversalRec(递归解法)  
  22.  * 5. 将二叉查找树变为有序的双向链表: convertBST2DLLRec, convertBST2DLL  
  23.  * 6. 求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel 
  24.  * 7. 求二叉树中叶子节点的个数:getNodeNumLeafRec, getNodeNumLeaf  
  25.  * 8. 判断两棵二叉树是否相同的树:isSameRec, isSame 
  26.  * 9. 判断二叉树是不是平衡二叉树:isAVLRec  
  27.  * 10. 求二叉树的镜像(破坏和不破坏原来的树两种情况): 
  28.  *     mirrorRec, mirrorCopyRec 
  29.  *     mirror, mirrorCopy  
  30.  * 10.1 判断两个树是否互相镜像:isMirrorRec isMirror 
  31.  * 11. 求二叉树中两个节点的最低公共祖先节点: 
  32.  *      LAC        求解最小公共祖先, 使用list来存储path. 
  33.  *      LCABstRec  递归求解BST树. 
  34.  *      LCARec     递归算法 . 
  35.  * 12. 求二叉树中节点的最大距离:getMaxDistanceRec  
  36.  * 13. 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec 
  37.  * 14. 判断二叉树是不是完全二叉树:isCompleteBinaryTree, isCompleteBinaryTreeRec 
  38.  * 15. 找出二叉树中最长连续子串(即全部往左的连续节点,或是全部往右的连续节点)findLongest 
  39.  */    
  40.   
  41. public class TreeDemo {  
  42.     /*  
  43.             1   
  44.            / \   
  45.           2   3   
  46.          / \   \   
  47.         4   5   6       
  48.     */    
  49.     public static void main(String[] args) {  
  50.         TreeNode r1 = new TreeNode(1);  
  51.         TreeNode r2 = new TreeNode(2);  
  52.         TreeNode r3 = new TreeNode(3);  
  53.         TreeNode r4 = new TreeNode(4);  
  54.         TreeNode r5 = new TreeNode(5);  
  55.         TreeNode r6 = new TreeNode(6);  
  56.           
  57. /*                     
  58.        10   
  59.        / \   
  60.       6   14   
  61.      / \   \   
  62.     4   8   16 
  63.    / 
  64.   0         
  65. */   
  66.         /*  
  67.         1   
  68.        / \   
  69.       2   3   
  70.      / \   \   
  71.     4   5   6       
  72. */    
  73. //        TreeNode r1 = new TreeNode(10);  
  74. //        TreeNode r2 = new TreeNode(6);  
  75. //        TreeNode r3 = new TreeNode(14);  
  76. //        TreeNode r4 = new TreeNode(4);  
  77. //        TreeNode r5 = new TreeNode(8);  
  78. //        TreeNode r6 = new TreeNode(16);  
  79.           
  80.         TreeNode r7 = new TreeNode(0);  
  81.           
  82.         r1.left = r2;  
  83.         r1.right = r3;  
  84.         r2.left = r4;  
  85.         r2.right = r5;  
  86.         r3.right = r6;  
  87.           
  88.         r4.left = r7;  
  89.   
  90.         TreeNode t1 = new TreeNode(10);  
  91.         TreeNode t2 = new TreeNode(6);  
  92.         TreeNode t3 = new TreeNode(14);  
  93.         TreeNode t4 = new TreeNode(4);  
  94.         TreeNode t5 = new TreeNode(8);  
  95.         TreeNode t6 = new TreeNode(16);  
  96.           
  97.         TreeNode t7 = new TreeNode(0);  
  98.           
  99.         TreeNode t8 = new TreeNode(0);  
  100.         TreeNode t9 = new TreeNode(0);  
  101.         TreeNode t10 = new TreeNode(0);  
  102.         TreeNode t11 = new TreeNode(0);  
  103.           
  104.           
  105.         t1.left = t2;  
  106.         t1.right = t3;  
  107.         t2.left = t4;  
  108.         t2.right = t5;  
  109.         t3.left = t6;  
  110.         t3.right = t7;  
  111.           
  112.         t4.left = t8;  
  113.         //t4.right = t9;  
  114.         t5.right = t9;  
  115.           
  116.           
  117.         // test distance  
  118. //        t5.right = t8;  
  119. //        t8.right = t9;  
  120. //        t9.right = t10;  
  121. //        t10.right = t11;  
  122.           
  123.         /*  
  124.         10   
  125.         / \   
  126.        6   14   
  127.       / \   \   
  128.      4   8   16 
  129.     / 
  130.    0         
  131.  */   
  132. //        System.out.println(LCABstRec(t1, t2, t4).val);  
  133. //        System.out.println(LCABstRec(t1, t2, t6).val);  
  134. //        System.out.println(LCABstRec(t1, t4, t6).val);  
  135. //        System.out.println(LCABstRec(t1, t4, t7).val);  
  136. //        System.out.println(LCABstRec(t1, t3, t6).val);  
  137. //          
  138. //        System.out.println(LCA(t1, t2, t4).val);  
  139. //        System.out.println(LCA(t1, t2, t6).val);  
  140. //        System.out.println(LCA(t1, t4, t6).val);  
  141. //        System.out.println(LCA(t1, t4, t7).val);  
  142. //        System.out.println(LCA(t1, t3, t6).val);  
  143. //        System.out.println(LCA(t1, t6, t6).val);  
  144.           
  145.         //System.out.println(getMaxDistanceRec(t1));  
  146.           
  147.         //System.out.println(isSame(r1, t1));  
  148.           
  149. //        System.out.println(isAVLRec(r1));  
  150. //          
  151. //        preorderTraversalRec(r1);  
  152. //        //mirrorRec(r1);  
  153. //        //TreeNode r1Mirror = mirror(r1);  
  154. //          
  155. //        TreeNode r1MirrorCopy = mirrorCopy(r1);  
  156. //        System.out.println();  
  157. //        //preorderTraversalRec(r1Mirror);  
  158. //        preorderTraversalRec(r1MirrorCopy);  
  159. //          
  160. //        System.out.println();  
  161. //          
  162. //        System.out.println(isMirrorRec(r1, r1MirrorCopy));  
  163. //        System.out.println(isMirror(r1, r1MirrorCopy));  
  164.           
  165.           
  166.         //System.out.println(getNodeNumKthLevelRec(r1, 5));  
  167.           
  168.         //System.out.println(getNodeNumLeaf(r1));  
  169.           
  170. //      System.out.println(getNodeNumRec(null));  
  171. //      System.out.println(getNodeNum(r1));  
  172.         //System.out.println(getDepthRec(null));  
  173. //        System.out.println(getDepth(r1));  
  174. //          
  175. //        preorderTraversalRec(r1);  
  176. //        System.out.println();  
  177. //        preorderTraversal(r1);  
  178. //        System.out.println();  
  179. //        inorderTraversalRec(r1);  
  180. //          
  181. //        System.out.println();  
  182. //          inorderTraversal(r1);  
  183. //        postorderTraversalRec(r1);  
  184. //        System.out.println();  
  185. //        postorderTraversal(r1);  
  186. //        System.out.println();  
  187. //        levelTraversal(r1);  
  188. //          
  189. //        System.out.println();  
  190. //        levelTraversalRec(r1);  
  191.           
  192. //        TreeNode ret = convertBST2DLLRec(r1);  
  193. //        while (ret != null) {  
  194. //            System.out.print(ret.val + " ");  
  195. //            ret = ret.right;  
  196. //        }  
  197.           
  198. //        TreeNode ret2 = convertBST2DLL(r1);  
  199. //        while (ret2.right != null) {  
  200. //            ret2 = ret2.right;  
  201. //        }  
  202. //          
  203. //        while (ret2 != null) {  
  204. //            System.out.print(ret2.val + " ");  
  205. //            ret2 = ret2.left;  
  206. //        }  
  207. //          
  208. //        TreeNode ret = convertBST2DLL(r1);  
  209. //        while (ret != null) {  
  210. //            System.out.print(ret.val + " ");  
  211. //            ret = ret.right;  
  212. //        }  
  213.           
  214. //        System.out.println();  
  215. //        System.out.println(findLongest(r1));  
  216. //        System.out.println();  
  217. //        System.out.println(findLongest2(r1));  
  218.           
  219.         // test the rebuildBinaryTreeRec.  
  220.         //test_rebuildBinaryTreeRec();  
  221.           
  222.         System.out.println(isCompleteBinaryTreeRec(t1));  
  223.         System.out.println(isCompleteBinaryTree(t1));  
  224.     }  
  225.       
  226.     public static void test_rebuildBinaryTreeRec() {  
  227.         ArrayList list1 = new ArrayList();  
  228.         list1.add(1);  
  229.         list1.add(2);  
  230.         list1.add(4);  
  231.         list1.add(5);  
  232.         list1.add(3);  
  233.         list1.add(6);  
  234.         list1.add(7);  
  235.         list1.add(8);  
  236.           
  237.         ArrayList list2 = new ArrayList();  
  238.         list2.add(4);  
  239.         list2.add(2);  
  240.         list2.add(5);  
  241.         list2.add(1);  
  242.         list2.add(3);  
  243.         list2.add(7);  
  244.         list2.add(6);  
  245.         list2.add(8);  
  246.           
  247.         TreeNode root = rebuildBinaryTreeRec(list1, list2);  
  248.         preorderTraversalRec(root);  
  249.         System.out.println();  
  250.         postorderTraversalRec(root);  
  251.     }  
  252.       
  253.     private static class TreeNode{  
  254.         int val;  
  255.         TreeNode left;  
  256.         TreeNode right;  
  257.         public TreeNode(int val){  
  258.             this.val = val;  
  259.             left = null;  
  260.             right = null;                      
  261.         }  
  262.     }  
  263.       
  264.     /* 
  265.      * null返回0,然后把左右子树的size加上即可。 
  266.      * */  
  267.     public static int getNodeNumRec(TreeNode root) {  
  268.         if (root == null) {  
  269.             return 0;  
  270.         }  
  271.                   
  272.         return getNodeNumRec(root.left) + getNodeNumRec(root.right) + 1;  
  273.     }  
  274.   
  275.     /**  
  276.      *  求二叉树中的节点个数迭代解法O(n):基本思想同LevelOrderTraversal,  
  277.      *  即用一个Queue,在Java里面可以用LinkedList来模拟   
  278.      */    
  279.     public static int getNodeNum(TreeNode root) {  
  280.         if (root == null) {  
  281.             return 0;  
  282.         }  
  283.           
  284.         Queue q = new LinkedList();   
  285.         q.offer(root);  
  286.           
  287.         int cnt = 0;  
  288.         while (!q.isEmpty()) {  
  289.             TreeNode node = q.poll();  
  290.             if (node.left != null) {  
  291.                 q.offer(node.left);  
  292.             }  
  293.               
  294.             if (node.right != null) {  
  295.                 q.offer(node.right);  
  296.             }  
  297.               
  298.             cnt++;  
  299.         }  
  300.           
  301.         return cnt;  
  302.     }  
  303.       
  304.     public static int getDepthRec(TreeNode root) {  
  305.         if (root == null) {  
  306.             return -1;  
  307.         }  
  308.           
  309.         return Math.max(getDepthRec(root.left), getDepthRec(root.right)) + 1;  
  310.     }  
  311.       
  312.     /* 
  313.      * 可以用 level LevelOrderTraversal 来实现,我们用一个dummyNode来分隔不同的层,这样即可计算出实际的depth. 
  314.      *      1   
  315.            / \   
  316.           2   3   
  317.          / \   \   
  318.         4   5   6 
  319.      *  
  320.      * 在队列中如此排列: 1, dummy, 2, 3, dummy, 4, 5, 5, dummy   
  321.      *  
  322.     */    
  323.     public static int getDepth(TreeNode root) {  
  324.         if (root == null) {  
  325.             return 0;  
  326.         }  
  327.           
  328.         TreeNode dummy = new TreeNode(0);  
  329.         Queue q = new LinkedList();  
  330.         q.offer(root);  
  331.         q.offer(dummy);  
  332.           
  333.         int depth = -1;  
  334.         while (!q.isEmpty()) {  
  335.             TreeNode curr = q.poll();  
  336.             if (curr == dummy) {  
  337.                 depth++;  
  338.                 if (!q.isEmpty()) {  // 使用DummyNode来区分不同的层, 如果下一层不是为空,则应该在尾部加DummyNode.  
  339.                     q.offer(dummy);  
  340.                 }  
  341.             }  
  342.               
  343.             if (curr.left != null) {  
  344.                 q.offer(curr.left);  
  345.             }  
  346.             if (curr.right != null) {  
  347.                 q.offer(curr.right);  
  348.             }  
  349.         }  
  350.           
  351.         return depth;  
  352.     }  
  353.       
  354.     /* 
  355.      * 3. 前序遍历,中序遍历,后序遍历: preorderTraversalRec, preorderTraversal, inorderTraversalRec, postorderTraversalRec  
  356.      * (https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_2) 
  357.      * */  
  358.     public static void preorderTraversalRec(TreeNode root) {  
  359.         if (root == null) {  
  360.             return;  
  361.         }  
  362.           
  363.         System.out.print(root.val + " ");  
  364.         preorderTraversalRec(root.left);  
  365.         preorderTraversalRec(root.right);  
  366.     }  
  367.       
  368.     /* 
  369.      * 前序遍历,Iteration 算法. 把根节点存在stack中。 
  370.      * */  
  371.     public static void preorderTraversal(TreeNode root) {  
  372.         if (root == null) {  
  373.             return;  
  374.         }  
  375.           
  376.         Stack s = new Stack();  
  377.         s.push(root);  
  378.           
  379.         while (!s.isEmpty()) {  
  380.             TreeNode node = s.pop();  
  381.             System.out.print(node.val + " ");  
  382.             if (node.right != null) { //  
  383.                 s.push(node.right);  
  384.             }  
  385.               
  386.             // 我们需要先压入右节点,再压入左节点,这样就可以先弹出左节点。   
  387.             if (node.left != null) {  
  388.                 s.push(node.left);  
  389.             }                         
  390.         }  
  391.     }  
  392.       
  393.     /* 
  394.      * 中序遍历 
  395.      * */  
  396.     public static void inorderTraversalRec(TreeNode root) {  
  397.         if (root == null) {  
  398.             return;  
  399.         }  
  400.           
  401.         inorderTraversalRec(root.left);  
  402.         System.out.print(root.val + " ");  
  403.         inorderTraversalRec(root.right);  
  404.     }  
  405.       
  406.     /**  
  407.      * 中序遍历迭代解法 ,用栈先把根节点的所有左孩子都添加到栈内,  
  408.      * 然后输出栈顶元素,再处理栈顶元素的右子树  
  409.      * http://www.youtube.com/watch?v=50v1sJkjxoc  
  410.      *   
  411.      * 还有一种方法能不用递归和栈,基于线索二叉树的方法,较麻烦以后补上  
  412.      * http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/  
  413.      */    
  414.     public static void inorderTraversal(TreeNode root) {  
  415.         if (root == null) {  
  416.             return;  
  417.         }  
  418.           
  419.         Stack s = new Stack();  
  420.           
  421.         TreeNode cur = root;  
  422.           
  423.         while(true) {  
  424.             // 把当前节点的左节点都push到栈中.  
  425.             while (cur != null) {  
  426.                 s.push(cur);  
  427.                 cur = cur.left;  
  428.             }  
  429.               
  430.             if (s.isEmpty()) {  
  431.                 break;  
  432.             }  
  433.               
  434.             // 因为此时已经没有左孩子了,所以输出栈顶元素   
  435.             cur = s.pop();  
  436.             System.out.print(cur.val + " ");  
  437.               
  438.             // 准备处理右子树    
  439.             cur = cur.right;              
  440.         }  
  441.     }  
  442.       
  443.     // 后序遍历  
  444.     /* 
  445.      *      1   
  446.            / \   
  447.           2   3   
  448.          / \   \   
  449.         4   5   6 
  450.          
  451.         if put into the stack directly, then it should be: 
  452.         1, 2, 4, 5, 3, 6 in the stack. 
  453.         when pop, it should be: 6, 3, 5, 4, 2, 1 
  454.          
  455.         if I  
  456.      * */  
  457.       
  458.     public static void postorderTraversalRec(TreeNode root) {  
  459.         if (root == null) {  
  460.             return;  
  461.         }  
  462.           
  463.         postorderTraversalRec(root.left);  
  464.         postorderTraversalRec(root.right);  
  465.         System.out.print(root.val + " ");  
  466.     }  
  467.       
  468.     /**  
  469.      *  后序遍历迭代解法  
  470.      *  http://www.youtube.com/watch?v=hv-mJUs5mvU  
  471.      *  http://blog.csdn.net/tang_jin2015/article/details/8545457 
  472.      *  从左到右的后序 与从右到左的前序的逆序是一样的,所以就简单喽! 哈哈 
  473.      *  用另外一个栈进行翻转即可喽  
  474.      */   
  475.     public static void postorderTraversal(TreeNode root) {  
  476.         if (root == null) {  
  477.             return;  
  478.         }  
  479.           
  480.         Stack s = new Stack();  
  481.         Stack out = new Stack();  
  482.           
  483.         s.push(root);  
  484.         while(!s.isEmpty()) {  
  485.             TreeNode cur = s.pop();  
  486.             out.push(cur);  
  487.               
  488.             if (cur.left != null) {  
  489.                 s.push(cur.left);  
  490.             }  
  491.             if (cur.right != null) {  
  492.                 s.push(cur.right);  
  493.             }  
  494.         }  
  495.           
  496.         while(!out.isEmpty()) {  
  497.             System.out.print(out.pop().val + " ");  
  498.         }  
  499.     }  
  500.       
  501.     /* 
  502.      * 分层遍历二叉树(按层次从上往下,从左往右)迭代  
  503.      * 其实就是广度优先搜索,使用队列实现。队列初始化,将根节点压入队列。当队列不为空,进行如下操作:弹出一个节点  
  504.      * ,访问,若左子节点或右子节点不为空,将其压入队列  
  505.      * */  
  506.     public static void levelTraversal(TreeNode root) {  
  507.         if (root == null) {  
  508.             return;  
  509.         }  
  510.           
  511.         Queue q = new LinkedList();  
  512.         q.offer(root);  
  513.           
  514.         while (!q.isEmpty()) {  
  515.             TreeNode cur = q.poll();  
  516.               
  517.             System.out.print(cur.val + " ");  
  518.             if (cur.left != null) {  
  519.                 q.offer(cur.left);  
  520.             }  
  521.             if (cur.right != null) {  
  522.                 q.offer(cur.right);  
  523.             }  
  524.         }  
  525.     }  
  526.       
  527.     public static void levelTraversalRec(TreeNode root) {  
  528.         ArrayList> ret = new ArrayList>();  
  529.         levelTraversalVisit(root, 0, ret);  
  530.         System.out.println(ret);  
  531.     }  
  532.       
  533.     /**  
  534.      *  分层遍历二叉树(递归)  
  535.      *  很少有人会用递归去做level traversal  
  536.      *  基本思想是用一个大的ArrayList,里面包含了每一层的ArrayList。  
  537.      *  大的ArrayList的size和level有关系  
  538.      *    
  539.      *  http://discuss.leetcode.com/questions/49/binary-tree-level-order-traversal#answer-container-2543  
  540.      */    
  541.     public static void levelTraversalVisit(TreeNode root, int level, ArrayList> ret) {  
  542.         if (root == null) {  
  543.             return;  
  544.         }  
  545.           
  546.         // 如果ArrayList的层数不够用, 则新添加一层  
  547.         // when size = 3, level: 0, 1, 2  
  548.         if (level >= ret.size()) {  
  549.             ret.add(new ArrayList());  
  550.         }  
  551.           
  552.         // visit 当前节点  
  553.         ret.get(level).add(root.val);  
  554.           
  555.         // 将左子树, 右子树添加到对应的层。  
  556.         levelTraversalVisit(root.left, level + 1, ret);  
  557.         levelTraversalVisit(root.right, level + 1, ret);  
  558.     }  
  559.       
  560.     /* 
  561.      * 题目要求:将二叉查找树转换成排序的双向链表,不能创建新节点,只调整指针。 
  562.        查找树的结点定义如下: 
  563.        既然是树,其定义本身就是递归的,自然用递归算法处理就很容易。将根结点的左子树和右子树转换为有序的双向链表, 
  564.        然后根节点的left指针指向左子树结果的最后一个结点,同时左子树最后一个结点的right指针指向根节点; 
  565.        根节点的right指针指向右子树结果的第一个结点, 
  566.        同时右子树第一个结点的left指针指向根节点。 
  567.      * */  
  568.     public static TreeNode convertBST2DLLRec(TreeNode root) {  
  569.         return convertBST2DLLRecHelp(root)[0];  
  570.     }  
  571.       
  572.     /* 
  573.      * ret[0] 代表左指针 
  574.      * ret[1] 代表右指针 
  575.      * */  
  576.     public static TreeNode[] convertBST2DLLRecHelp(TreeNode root) {  
  577.         TreeNode[] ret = new TreeNode[2];  
  578.         ret[0] = null;  
  579.         ret[1] = null;  
  580.                   
  581.         if (root == null) {  
  582.             return ret;  
  583.         }  
  584.           
  585.         if (root.left != null) {  
  586.             TreeNode left[] = convertBST2DLLRecHelp(root.left);  
  587.             left[1].right = root;  // 将左子树的尾节点连接到根  
  588.             root.left = left[1];  
  589.               
  590.             ret[0] = left[0];  
  591.         } else {  
  592.             ret[0] = root;   // 左节点返回root.  
  593.         }  
  594.           
  595.         if (root.right != null) {  
  596.             TreeNode right[] = convertBST2DLLRecHelp(root.right);  
  597.             right[0].left = root;  // 将右子树的头节点连接到根  
  598.             root.right = right[0];  
  599.               
  600.             ret[1] = right[1];  
  601.         } else {  
  602.             ret[1] = root;  // 右节点返回root.  
  603.         }  
  604.           
  605.         return ret;  
  606.     }  
  607.       
  608.     /**  
  609.      * 将二叉查找树变为有序的双向链表 迭代解法  
  610.      * 类似inOrder traversal的做法  
  611.      */    
  612.     public static TreeNode convertBST2DLL(TreeNode root) {  
  613.         while (root == null) {  
  614.             return null;  
  615.         }  
  616.           
  617.         TreeNode pre = null;  
  618.         Stack s = new Stack();  
  619.         TreeNode cur = root;  
  620.         TreeNode head = null;       // 链表头  
  621.           
  622.         while (true) {  
  623.             while (cur != null) {  
  624.                 s.push(cur);  
  625.                 cur = cur.left;  
  626.             }  
  627.               
  628.             // if stack is empty, just break;  
  629.             if (s.isEmpty()) {  
  630.                 break;  
  631.             }  
  632.               
  633.             cur = s.pop();   
  634.             if (head == null) {  
  635.                 head = cur;  
  636.             }  
  637.   
  638.             // link pre and cur.  
  639.             cur.left = pre;  
  640.             if (pre != null) {  
  641.                 pre.right = cur;  
  642.             }  
  643.               
  644.             // 左节点已经处理完了,处理右节点  
  645.             cur = cur.right;  
  646.             pre = cur;  
  647.         }  
  648.           
  649.         return root;  
  650.     }  
  651.   
  652. /* 
  653.  *  * 6. 求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel  
  654.  * */  
  655.     public static int getNodeNumKthLevel(TreeNode root, int k) {  
  656.         if (root == null || k <= 0) {  
  657.             return 0;  
  658.         }  
  659.           
  660.         int level = 0;  
  661.           
  662.         Queue q = new LinkedList();  
  663.         q.offer(root);  
  664.           
  665.         TreeNode dummy = new TreeNode(0);  
  666.         int cnt = 0// record the size of the level.  
  667.           
  668.         q.offer(dummy);  
  669.         while (!q.isEmpty()) {  
  670.             TreeNode node = q.poll();  
  671.               
  672.             if (node == dummy) {  
  673.                 level++;  
  674.                 if (level == k) {  
  675.                     return cnt;  
  676.                 }  
  677.                 cnt = 0// reset the cnt;  
  678.                 if (q.isEmpty()) {  
  679.                     break;  
  680.                 }  
  681.                 q.offer(dummy);  
  682.                 continue;  
  683.             }  
  684.               
  685.             cnt++;  
  686.             if (node.left != null) {  
  687.                 q.offer(node.left);  
  688.             }  
  689.               
  690.             if (node.right != null) {  
  691.                 q.offer(node.right);  
  692.             }  
  693.         }  
  694.           
  695.         return 0;  
  696.     }  
  697.       
  698.     /* 
  699.      *  * 6. 求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel  
  700.      * */  
  701.     public static int getNodeNumKthLevelRec(TreeNode root, int k) {  
  702.         if (root == null || k <= 0) {  
  703.             return 0;  
  704.         }  
  705.           
  706.         if (k == 1) {  
  707.             return 1;  
  708.         }  
  709.           
  710.         // 将左子树及右子树在K层的节点个数相加.  
  711.         return getNodeNumKthLevelRec(root.left, k - 1) + getNodeNumKthLevelRec(root.right, k - 1);  
  712.     }  
  713.       
  714.     /* 
  715.      * 7. getNodeNumLeafRec  把左子树和右子树的叶子节点加在一起即可 
  716.      * */  
  717.     public static int getNodeNumLeafRec(TreeNode root) {  
  718.         if (root == null) {  
  719.             return 0;  
  720.         }  
  721.           
  722.         if (root.left == null && root.right == null) {  
  723.             return 1;  
  724.         }  
  725.           
  726.         return getNodeNumLeafRec(root.left) + getNodeNumLeafRec(root.right);  
  727.     }  
  728.       
  729.     /* 7. getNodeNumLeaf 
  730.      * 随便使用一种遍历方法都可以,比如,中序遍历。 
  731.      * inorderTraversal,判断是不是叶子节点。 
  732.      * */  
  733.     public static int getNodeNumLeaf(TreeNode root) {  
  734.         if (root == null) {  
  735.             return 0;  
  736.         }  
  737.           
  738.         int cnt = 0;  
  739.           
  740.         // we can use inorderTraversal travesal to do it.  
  741.         Stack s = new Stack();  
  742.         TreeNode cur = root;  
  743.           
  744.         while (true) {  
  745.             while (cur != null) {  
  746.                 s.push(cur);  
  747.                 cur = cur.left;  
  748.             }  
  749.               
  750.             if (s.isEmpty()) {  
  751.                 break;  
  752.             }  
  753.               
  754.             // all the left child has been put into the stack, let's deal with the   
  755.             // current node.  
  756.             cur = s.pop();  
  757.             if (cur.left == null && cur.right == null) {  
  758.                 cnt++;  
  759.             }  
  760.             cur = cur.right;  
  761.         }  
  762.           
  763.         return cnt;  
  764.     }  
  765.       
  766.     /* 
  767.      * 8. 判断两棵二叉树是否相同的树。  
  768.      * 递归解法:   
  769.      * (1)如果两棵二叉树都为空,返回真  
  770.      * (2)如果两棵二叉树一棵为空,另一棵不为空,返回假   
  771.      * (3)如果两棵二叉树都不为空,如果对应的左子树和右子树都同构返回真,其他返回假  
  772.      * */  
  773.     public static boolean isSameRec(TreeNode r1, TreeNode r2) {  
  774.         // both are null.  
  775.         if (r1 == null && r2 == null) {  
  776.             return true;  
  777.         }  
  778.           
  779.         // one is null.  
  780.         if (r1 == null || r2 == null) {  
  781.             return false;  
  782.         }  
  783.           
  784.         // 1. the value of the root should be the same;  
  785.         // 2. the left tree should be the same.  
  786.         // 3. the right tree should be the same.  
  787.         return r1.val == r2.val &&   
  788.                 isSameRec(r1.left, r2.left) && isSameRec(r1.right, r2.right);  
  789.     }  
  790.       
  791.     /* 
  792.      * 8. 判断两棵二叉树是否相同的树。 
  793.      * 迭代解法  
  794.      * 我们直接用中序遍历来比较就好啦  
  795.      * */  
  796.     public static boolean isSame(TreeNode r1, TreeNode r2) {  
  797.         // both are null.  
  798.         if (r1 == null && r2 == null) {  
  799.             return true;  
  800.         }  
  801.           
  802.         // one is null.  
  803.         if (r1 == null || r2 == null) {  
  804.             return false;  
  805.         }  
  806.           
  807.         Stack s1 = new Stack();  
  808.         Stack s2 = new Stack();  
  809.           
  810.         TreeNode cur1 = r1;  
  811.         TreeNode cur2 = r2;  
  812.           
  813.         while (true) {  
  814.             while (cur1 != null && cur2 != null) {  
  815.                 s1.push(cur1);  
  816.                 s2.push(cur2);  
  817.                 cur1 = cur1.left;  
  818.                 cur2 = cur2.left;  
  819.             }  
  820.               
  821.             if (cur1 != null || cur2 != null) {  
  822.                 return false;  
  823.             }  
  824.               
  825.             if (s1.isEmpty() && s2.isEmpty()) {  
  826.                 break;  
  827.             }  
  828.               
  829.             cur1 = s1.pop();  
  830.             cur2 = s2.pop();  
  831.             if (cur1.val != cur2.val) {  
  832.                 return false;  
  833.             }  
  834.               
  835.             cur1 = cur1.right;  
  836.             cur2 = cur2.right;  
  837.         }  
  838.           
  839.         return true;  
  840.     }  
  841.       
  842. /* 
  843.  *  
  844.  *  9. 判断二叉树是不是平衡二叉树:isAVLRec 
  845.  *     1. 左子树,右子树的高度差不能超过1 
  846.  *     2. 左子树,右子树都是平衡二叉树。  
  847.  *       
  848.  */  
  849.     public static boolean isAVLRec(TreeNode root) {  
  850.         if (root == null) {  
  851.             return true;  
  852.         }  
  853.           
  854.         // 左子树,右子树都必须是平衡二叉树。   
  855.         if (!isAVLRec(root.left) || !isAVLRec(root.right)) {  
  856.             return false;  
  857.         }  
  858.           
  859.         int dif = Math.abs(getDepthRec(root.left) - getDepthRec(root.right));  
  860.         if (dif > 1) {  
  861.             return false;  
  862.         }  
  863.           
  864.         return true;  
  865.     }  
  866.       
  867.     /**  
  868.      * 10. 求二叉树的镜像 递归解法: 
  869.      *  
  870.      *   (1) 破坏原来的树 
  871.      *    
  872.      *      1               1 
  873.      *     /                 \ 
  874.      *    2     ----->        2 
  875.      *     \                 / 
  876.      *      3               3 
  877.      * */    
  878.     public static TreeNode mirrorRec(TreeNode root) {    
  879.         if (root == null) {  
  880.             return null;  
  881.         }  
  882.           
  883.         // 先把左右子树分别镜像,并且交换它们  
  884.         TreeNode tmp = root.right;  
  885.         root.right = mirrorRec(root.left);  
  886.         root.left = mirrorRec(tmp);  
  887.           
  888.         return root;  
  889.     }    
  890.       
  891.     /**  
  892.      * 10. 求二叉树的镜像 Iterator解法: 
  893.      *  
  894.      *   (1) 破坏原来的树 
  895.      *    
  896.      *      1               1 
  897.      *     /                 \ 
  898.      *    2     ----->        2 
  899.      *     \                 / 
  900.      *      3               3 
  901.      *       
  902.      *  应该可以使用任何一种Traversal 方法。  
  903.      *  我们现在可以试看看使用最简单的前序遍历。 
  904.      * */    
  905.     public static TreeNode mirror(TreeNode root) {    
  906.         if (root == null) {  
  907.             return null;  
  908.         }  
  909.           
  910.         Stack s = new Stack();  
  911.         s.push(root);  
  912.           
  913.         while (!s.isEmpty()) {  
  914.             TreeNode cur = s.pop();  
  915.               
  916.             // 交换当前节点的左右节点  
  917.             TreeNode tmp = cur.left;  
  918.             cur.left = cur.right;  
  919.             cur.right = tmp;  
  920.               
  921.             // traversal 左节点,右节点。  
  922.             if (cur.right != null) {  
  923.                 s.push(cur.right);  
  924.             }  
  925.               
  926.             if (cur.left != null) {  
  927.                 s.push(cur.left);  
  928.             }  
  929.         }  
  930.           
  931.         return root;  
  932.     }    
  933.       
  934.     /**  
  935.      * 10. 求二叉树的镜像 Iterator解法: 
  936.      *  
  937.      *   (2) 创建一个新的树 
  938.      *    
  939.      *      1               1 
  940.      *     /                 \ 
  941.      *    2     ----->        2 
  942.      *     \                 / 
  943.      *      3               3 
  944.      *       
  945.      *  应该可以使用任何一种Traversal 方法。  
  946.      *  我们现在可以试看看使用最简单的前序遍历。 
  947.      *  前序遍历我们可以立刻把新建好的左右节点创建出来,比较方便  
  948.      * */    
  949.     public static TreeNode mirrorCopy(TreeNode root) {    
  950.         if (root == null) {  
  951.             return null;  
  952.         }  
  953.           
  954.         Stack s = new Stack();  
  955.         Stack sCopy = new Stack();  
  956.         s.push(root);  
  957.           
  958.         TreeNode rootCopy = new TreeNode(root.val);  
  959.         sCopy.push(rootCopy);  
  960.           
  961.         while (!s.isEmpty()) {  
  962.             TreeNode cur = s.pop();  
  963.             TreeNode curCopy = sCopy.pop();  
  964.               
  965.             // traversal 左节点,右节点。  
  966.             if (cur.right != null) {  
  967.                   
  968.                 // copy 在这里做比较好,因为我们可以容易地找到它的父节点  
  969.                 TreeNode leftCopy = new TreeNode(cur.right.val);  
  970.                 curCopy.left = leftCopy;  
  971.                 s.push(cur.right);  
  972.                 sCopy.push(curCopy.left);  
  973.             }  
  974.               
  975.             if (cur.left != null) {  
  976.                 // copy 在这里做比较好,因为我们可以容易地找到它的父节点  
  977.                 TreeNode rightCopy = new TreeNode(cur.left.val);  
  978.                 curCopy.right = rightCopy;  
  979.                 s.push(cur.left);  
  980.                 sCopy.push(curCopy.right);  
  981.             }  
  982.         }  
  983.           
  984.         return rootCopy;  
  985.     }    
  986.       
  987.     /**  
  988.      * 10. 求二叉树的镜像 递归解法: 
  989.      *  
  990.      *   (1) 不破坏原来的树,新建一个树  
  991.      *    
  992.      *      1               1 
  993.      *     /                 \ 
  994.      *    2     ----->        2 
  995.      *     \                 / 
  996.      *      3               3 
  997.      * */    
  998.     public static TreeNode mirrorCopyRec(TreeNode root) {    
  999.         if (root == null) {  
  1000.             return null;  
  1001.         }  
  1002.           
  1003.         // 先把左右子树分别镜像,并且把它们连接到新建的root节点。  
  1004.         TreeNode rootCopy = new TreeNode(root.val);  
  1005.         rootCopy.left = mirrorCopyRec(root.right);  
  1006.         rootCopy.right = mirrorCopyRec(root.left);  
  1007.           
  1008.         return rootCopy;  
  1009.     }    
  1010.       
  1011.     /* 
  1012.      * 10.1. 判断两个树是否互相镜像 
  1013.      *  (1) 根必须同时为空,或是同时不为空 
  1014.      *  
  1015.      * 如果根不为空: 
  1016.      *  (1).根的值一样 
  1017.      *  (2).r1的左树是r2的右树的镜像 
  1018.      *  (3).r1的右树是r2的左树的镜像   
  1019.      * */  
  1020.     public static boolean isMirrorRec(TreeNode r1, TreeNode r2){    
  1021.         // 如果2个树都是空树  
  1022.         if (r1 == null && r2 == null) {  
  1023.             return true;  
  1024.         }  
  1025.           
  1026.         // 如果其中一个为空,则返回false.  
  1027.         if (r1 == null || r2 == null) {  
  1028.             return false;  
  1029.         }  
  1030.           
  1031.         // If both are not null, they should be:  
  1032.         // 1. have same value for root.  
  1033.         // 2. R1's left tree is the mirror of R2's right tree;  
  1034.         // 3. R2's right tree is the mirror of R1's left tree;  
  1035.         return r1.val == r2.val   
  1036.                 && isMirrorRec(r1.left, r2.right)  
  1037.                 && isMirrorRec(r1.right, r2.left);  
  1038.     }  
  1039.       
  1040.     /* 
  1041.      * 10.1. 判断两个树是否互相镜像 Iterator 做法 
  1042.      *  (1) 根必须同时为空,或是同时不为空 
  1043.      *  
  1044.      * 如果根不为空: 
  1045.      * traversal 整个树,判断它们是不是镜像,每次都按照反向来traversal   
  1046.      * (1). 当前节点的值相等 
  1047.      * (2). 当前节点的左右节点要镜像, 
  1048.      *    无论是左节点,还是右节点,对应另外一棵树的镜像位置,可以同时为空,或是同时不为空,但是不可以一个为空,一个不为空。       
  1049.      * */  
  1050.     public static boolean isMirror(TreeNode r1, TreeNode r2){    
  1051.         // 如果2个树都是空树  
  1052.         if (r1 == null && r2 == null) {  
  1053.             return true;  
  1054.         }  
  1055.           
  1056.         // 如果其中一个为空,则返回false.  
  1057.         if (r1 == null || r2 == null) {  
  1058.             return false;  
  1059.         }  
  1060.           
  1061.         Stack s1 = new Stack();  
  1062.         Stack s2 = new Stack();  
  1063.           
  1064.         s1.push(r1);  
  1065.         s2.push(r2);  
  1066.           
  1067.         while (!s1.isEmpty() && !s2.isEmpty()) {  
  1068.             TreeNode cur1 = s1.pop();  
  1069.             TreeNode cur2 = s2.pop();  
  1070.               
  1071.             // 弹出的节点的值必须相等   
  1072.             if (cur1.val != cur2.val) {  
  1073.                 return false;  
  1074.             }  
  1075.               
  1076.             // tree1的左节点,tree2的右节点,可以同时不为空,也可以同时为空,否则返回false.  
  1077.             TreeNode left1 = cur1.left;  
  1078.             TreeNode right1 = cur1.right;  
  1079.             TreeNode left2 = cur2.left;  
  1080.             TreeNode right2 = cur2.right;  
  1081.               
  1082.             if (left1 != null && right2 != null) {  
  1083.                 s1.push(left1);  
  1084.                 s2.push(right2);  
  1085.             } else if (!(left1 == null && right2 == null)) {  
  1086.                 return false;  
  1087.             }  
  1088.               
  1089.             // tree1的左节点,tree2的右节点,可以同时不为空,也可以同时为空,否则返回false.  
  1090.             if (right1 != null && left2 != null) {  
  1091.                 s1.push(right1);  
  1092.                 s2.push(left2);  
  1093.             } else if (!(right1 == null && left2 == null)) {  
  1094.                 return false;  
  1095.             }  
  1096.         }  
  1097.           
  1098.         return true;  
  1099.     }    
  1100.       
  1101.     /* 
  1102.      * 11. 求二叉树中两个节点的最低公共祖先节点: 
  1103.      * Recursion Version: 
  1104.      * LACRec  
  1105.      * 1. If found in the left tree, return the Ancestor. 
  1106.      * 2. If found in the right tree, return the Ancestor. 
  1107.      * 3. If Didn't find any of the node, return null. 
  1108.      * 4. If found both in the left and the right tree, return the root. 
  1109.      * */  
  1110.     public static TreeNode LACRec(TreeNode root, TreeNode node1, TreeNode node2) {  
  1111.         if (root == null || node1 == null || node2 == null) {  
  1112.             return null;  
  1113.         }  
  1114.           
  1115.         // If any of the node is the root, just return the root.  
  1116.         if (root == node1 || root == node2) {  
  1117.             return root;  
  1118.         }  
  1119.           
  1120.         // if no node is in the node, just recursively find it in LEFT and RIGHT tree.  
  1121.         TreeNode left = LACRec(root.left, node1, node2);  
  1122.         TreeNode right = LACRec(root.right, node1, node2);  
  1123.           
  1124.         if (left == null) {  // If didn't found in the left tree, then just return it from right.  
  1125.             return right;  
  1126.         } else if (right == null) { // Or if didn't found in the right tree, then just return it from the left side.  
  1127.             return left;  
  1128.         }   
  1129.           
  1130.         // if both right and right found a node, just return the root as the Common Ancestor.  
  1131.         return root;  
  1132.     }  
  1133.       
  1134.     /* 
  1135.      * 11. 求BST中两个节点的最低公共祖先节点: 
  1136.      * Recursive version: 
  1137.      * LCABst  
  1138.      *  
  1139.      * 1. If found in the left tree, return the Ancestor. 
  1140.      * 2. If found in the right tree, return the Ancestor. 
  1141.      * 3. If Didn't find any of the node, return null. 
  1142.      * 4. If found both in the left and the right tree, return the root. 
  1143.      * */  
  1144.     public static TreeNode LCABstRec(TreeNode root, TreeNode node1, TreeNode node2) {  
  1145.         if (root == null || node1 == null || node2 == null) {  
  1146.             return null;  
  1147.         }  
  1148.           
  1149.         // If any of the node is the root, just return the root.  
  1150.         if (root == node1 || root == node2) {  
  1151.             return root;  
  1152.         }  
  1153.           
  1154.         int min = Math.min(node1.val, node2.val);  
  1155.         int max = Math.max(node1.val, node2.val);  
  1156.           
  1157.         // if the values are smaller than the root value, just search them in the left tree.  
  1158.         if (root.val > max) {  
  1159.             return LCABstRec(root.left, node1, node2);  
  1160.         } else if (root.val < min) {  
  1161.         // if the values are larger than the root value, just search them in the right tree.      
  1162.             return LCABstRec(root.right, node1, node2);  
  1163.         }  
  1164.           
  1165.         // if root is in the middle, just return the root.  
  1166.         return root;  
  1167.     }  
  1168.       
  1169.     /* 
  1170.      * 解法1. 记录下path,并且比较之: 
  1171.      * LAC 
  1172.      * http://www.geeksforgeeks.org/lowest-common-ancestor-binary-tree-set-1/ 
  1173.      * */  
  1174.     public static TreeNode LCA(TreeNode root, TreeNode r1, TreeNode r2) {  
  1175.         // If the nodes have one in the root, just return the root.  
  1176.         if (root == null || r1 == null || r2 == null) {  
  1177.             return null;  
  1178.         }  
  1179.           
  1180.         ArrayList list1 = new ArrayList();  
  1181.         ArrayList list2 = new ArrayList();  
  1182.           
  1183.         boolean find1 = LCAPath(root, r1, list1);  
  1184.         boolean find2 = LCAPath(root, r2, list2);  
  1185.           
  1186.         // If didn't find any of the node, just return a null.  
  1187.         if (!find1 || !find2) {  
  1188.             return null;  
  1189.         }  
  1190.           
  1191.         // 注意: 使用Iterator 对于linkedlist可以提高性能。  
  1192.         // 所以 统一使用Iterator 来进行操作。  
  1193.         Iterator iter1 = list1.iterator();  
  1194.         Iterator iter2 = list2.iterator();  
  1195.           
  1196.         TreeNode last = null;  
  1197.         while (iter1.hasNext() && iter2.hasNext()) {  
  1198.             TreeNode tmp1 = iter1.next();  
  1199.             TreeNode tmp2 = iter2.next();  
  1200.               
  1201.             if (tmp1 != tmp2) {  
  1202.                 return last;  
  1203.             }  
  1204.               
  1205.             last = tmp1;  
  1206.         }  
  1207.           
  1208.         // If never find any node which is different, means Node 1 and Node 2 are the same one.  
  1209.         // so just return the last one.  
  1210.         return last;  
  1211.     }  
  1212.       
  1213.     public static boolean LCAPath(TreeNode root, TreeNode node, ArrayList path) {  
  1214.         // if didn't find, we should return a empty path.  
  1215.         if (root == null || node == null) {  
  1216.             return false;  
  1217.         }  
  1218.           
  1219.         // First add the root node.  
  1220.         path.add(root);  
  1221.           
  1222.         // if the node is in the left side.  
  1223.         if (root != node   
  1224.                 && !LCAPath(root.left, node, path)  
  1225.                 && !LCAPath(root.right, node, path)  
  1226.                 ) {  
  1227.             // Didn't find the node. should remove the node added before.  
  1228.             path.remove(root);  
  1229.             return false;  
  1230.         }  
  1231.           
  1232.         // found  
  1233.         return true;  
  1234.     }  
  1235.       
  1236.     /* 
  1237.      *  * 12. 求二叉树中节点的最大距离:getMaxDistanceRec 
  1238.      *   
  1239.      *  首先我们来定义这个距离: 
  1240.      *  距离定义为:两个节点间边的数目. 
  1241.      *  如: 
  1242.      *     1 
  1243.      *    / \ 
  1244.      *   2   3 
  1245.      *        \ 
  1246.      *         4 
  1247.      *   这里最大距离定义为2,4的距离,为3.       
  1248.      * 求二叉树中节点的最大距离 即二叉树中相距最远的两个节点之间的距离。 (distance / diameter)  
  1249.      * 递归解法: 
  1250.      * 返回值设计: 
  1251.      * 返回1. 深度, 2. 当前树的最长距离   
  1252.      * (1) 计算左子树的深度,右子树深度,左子树独立的链条长度,右子树独立的链条长度 
  1253.      * (2) 最大长度为三者之最: 
  1254.      *    a. 通过根节点的链,为左右深度+2 
  1255.      *    b. 左子树独立链 
  1256.      *    c. 右子树独立链。 
  1257.      *  
  1258.      * (3)递归初始条件: 
  1259.      *   当root == null, depth = -1.maxDistance = -1; 
  1260.      *    
  1261.      */    
  1262.     public static int getMaxDistanceRec(TreeNode root) {  
  1263.         return getMaxDistanceRecHelp(root).maxDistance;  
  1264.     }  
  1265.       
  1266.     public static Result getMaxDistanceRecHelp(TreeNode root) {  
  1267.         Result ret = new Result(-1, -1);  
  1268.           
  1269.         if (root == null) {  
  1270.             return ret;  
  1271.         }  
  1272.           
  1273.         Result left = getMaxDistanceRecHelp(root.left);  
  1274.         Result right = getMaxDistanceRecHelp(root.right);  
  1275.           
  1276.         // 深度应加1, the depth from the subtree to the root.  
  1277.         ret.depth = Math.max(left.depth, right.depth) + 1;  
  1278.           
  1279.         // 左子树,右子树与根的距离都要加1,所以通过根节点的路径为两边深度+2  
  1280.         int crossLen = left.depth + right.depth + 2;  
  1281.           
  1282.         // 求出cross根的路径,及左右子树的独立路径,这三者路径的最大值。  
  1283.         ret.maxDistance = Math.max(left.maxDistance, right.maxDistance);  
  1284.         ret.maxDistance = Math.max(ret.maxDistance, crossLen);  
  1285.           
  1286.         return ret;  
  1287.     }  
  1288.   
  1289.       
  1290.     private static class Result {  
  1291.         int depth;  
  1292.         int maxDistance;  
  1293.         public Result(int depth, int maxDistance) {  
  1294.             this.depth = depth;  
  1295.             this.maxDistance = maxDistance;  
  1296.         }  
  1297.     }  
  1298.       
  1299.     /* 
  1300.      *  13. 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec  
  1301.      *  We assume that there is no duplicate in the trees. 
  1302.      *  For example: 
  1303.      *          1 
  1304.      *         / \ 
  1305.      *        2   3 
  1306.      *       /\    \ 
  1307.      *      4  5    6 
  1308.      *              /\ 
  1309.      *             7  8   
  1310.      *              
  1311.      *  PreOrder should be: 1   2 4 5   3 6 7 8 
  1312.      *                      根   左子树    右子树   
  1313.      *  InOrder should be:  4 2 5   1   3 7 6 8 
  1314.      *                       左子树  根  右子树 
  1315.      * */                     
  1316.     public static TreeNode rebuildBinaryTreeRec(List preOrder, List inOrder) {  
  1317.         if (preOrder == null || inOrder == null) {  
  1318.             return null;  
  1319.         }  
  1320.           
  1321.         // If the traversal is empty, just return a NULL.  
  1322.         if (preOrder.size() == 0 || inOrder.size() == 0) {  
  1323.             return null;  
  1324.         }  
  1325.           
  1326.         // we can get the root from the preOrder.   
  1327.         // Because the first one is the root.  
  1328.         // So we just create the root node here.  
  1329.         TreeNode root = new TreeNode(preOrder.get(0));  
  1330.           
  1331.         List preOrderLeft;  
  1332.         List preOrderRight;  
  1333.         List inOrderLeft;  
  1334.         List inOrderRight;  
  1335.           
  1336.         // 获得在 inOrder中,根的位置  
  1337.         int rootInIndex = inOrder.indexOf(preOrder.get(0));  
  1338.         preOrderLeft = preOrder.subList(1, rootInIndex + 1);  
  1339.         preOrderRight = preOrder.subList(rootInIndex + 1, preOrder.size());  
  1340.           
  1341.         // 得到inOrder左边的左子树  
  1342.         inOrderLeft = inOrder.subList(0, rootInIndex);  
  1343.         inOrderRight = inOrder.subList(rootInIndex + 1, inOrder.size());  
  1344.   
  1345.         // 通过 Rec 来调用生成左右子树。  
  1346.         root.left = rebuildBinaryTreeRec(preOrderLeft, inOrderLeft);  
  1347.         root.right = rebuildBinaryTreeRec(preOrderRight, inOrderRight);  
  1348.           
  1349.         return root;          
  1350.     }  
  1351.       
  1352.     /* 
  1353.      * 14. 判断二叉树是不是完全二叉树:isCompleteBinaryTree, isCompleteBinaryTreeRec 
  1354.      * 进行level traversal, 一旦遇到一个节点的左节点为空,后面的节点的子节点都必须为空。而且不应该有下一行,其实就是队列中所有的 
  1355.      * 元素都不应该再有子元素。 
  1356.      * */  
  1357.       
  1358.     public static boolean isCompleteBinaryTree(TreeNode root) {  
  1359.         if (root == null) {  
  1360.             return false;  
  1361.         }  
  1362.           
  1363.         TreeNode dummyNode = new TreeNode(0);  
  1364.         Queue q = new LinkedList();  
  1365.           
  1366.         q.offer(root);  
  1367.         q.offer(dummyNode);  
  1368.           
  1369.         // if this is true, no node should have any child.  
  1370.         boolean noChild = false;  
  1371.           
  1372.         while (!q.isEmpty()) {  
  1373.             TreeNode cur = q.poll();  
  1374.             if (cur == dummyNode) {  
  1375.                 if (!q.isEmpty()) {  
  1376.                     q.offer(dummyNode);  
  1377.                 }  
  1378.                 // Dummy node不需要处理。   
  1379.                 continue;  
  1380.             }  
  1381.               
  1382.             if (cur.left != null) {  
  1383.                 // 如果标记被设置,则Queue中任何元素不应再有子元素。  
  1384.                 if (noChild) {  
  1385.                     return false;  
  1386.                 }  
  1387.                 q.offer(cur.left);  
  1388.             } else {  
  1389.                 // 一旦某元素没有左节点或是右节点,则之后所有的元素都不应有子元素。  
  1390.                 // 并且该元素不可以有右节点.  
  1391.                 noChild = true;  
  1392.             }  
  1393.               
  1394.             if (cur.right != null) {  
  1395.                 // 如果标记被设置,则Queue中任何元素不应再有子元素。  
  1396.                 if (noChild) {  
  1397.                     return false;  
  1398.                 }  
  1399.                 q.offer(cur.right);  
  1400.             } else {  
  1401.                 // 一旦某元素没有左节点或是右节点,则之后所有的元素都不应有子元素。  
  1402.                 noChild = true;  
  1403.             }  
  1404.         }  
  1405.           
  1406.         return true;  
  1407.     }  
  1408.       
  1409.     /* 
  1410.      * 14. 判断二叉树是不是完全二叉树:isCompleteBinaryTreeRec 
  1411.      *  
  1412.      *  
  1413.      *    我们可以分解为: 
  1414.      *    CompleteBinary Tree 的条件是: 
  1415.      *    1. 左右子树均为Perfect binary tree, 并且两者Height相同 
  1416.      *    2. 左子树为CompleteBinaryTree, 右子树为Perfect binary tree,并且两者Height差1 
  1417.      *    3. 左子树为Perfect Binary Tree,右子树为CompleteBinaryTree, 并且Height 相同 
  1418.      *     
  1419.      *    Base 条件: 
  1420.      *    (1) root = null: 为perfect & complete BinaryTree, Height -1; 
  1421.      *     
  1422.      *    而 Perfect Binary Tree的条件: 
  1423.      *    左右子树均为Perfect Binary Tree,并且Height 相同。 
  1424.      * */  
  1425.       
  1426.     public static boolean isCompleteBinaryTreeRec(TreeNode root) {  
  1427.         return isCompleteBinaryTreeRecHelp(root).isCompleteBT;  
  1428.     }  
  1429.       
  1430.     private static class ReturnBinaryTree {  
  1431.         boolean isCompleteBT;  
  1432.         boolean isPerfectBT;  
  1433.         int height;  
  1434.           
  1435.         ReturnBinaryTree(boolean isCompleteBT, boolean isPerfectBT, int height) {  
  1436.             this.isCompleteBT = isCompleteBT;  
  1437.             this.isPerfectBT = isPerfectBT;  
  1438.             this.height = height;  
  1439.         }  
  1440.     }  
  1441.       
  1442.     /* 
  1443.      * 我们可以分解为: 
  1444.      *    CompleteBinary Tree 的条件是: 
  1445.      *    1. 左右子树均为Perfect binary tree, 并且两者Height相同 
  1446.      *    2. 左子树为CompleteBinaryTree, 右子树为Perfect binary tree,并且两者Height差1 
  1447.      *    3. 左子树为Perfect Binary Tree,右子树为CompleteBinaryTree, 并且Height 相同 
  1448.      *     
  1449.      *    Base 条件: 
  1450.      *    (1) root = null: 为perfect & complete BinaryTree, Height -1; 
  1451.      *     
  1452.      *    而 Perfect Binary Tree的条件: 
  1453.      *    左右子树均为Perfect Binary Tree,并且Height 相同。 
  1454.      * */  
  1455.     public static ReturnBinaryTree isCompleteBinaryTreeRecHelp(TreeNode root) {  
  1456.         ReturnBinaryTree ret = new ReturnBinaryTree(truetrue, -1);  
  1457.           
  1458.         if (root == null) {  
  1459.             return ret;  
  1460.         }  
  1461.           
  1462.         ReturnBinaryTree left = isCompleteBinaryTreeRecHelp(root.left);  
  1463.         ReturnBinaryTree right = isCompleteBinaryTreeRecHelp(root.right);  
  1464.           
  1465.         // 树的高度为左树高度,右树高度的最大值+1  
  1466.         ret.height = 1 + Math.max(left.height, right.height);  
  1467.           
  1468.         // set the isPerfectBT  
  1469.         ret.isPerfectBT = false;  
  1470.         if (left.isPerfectBT && right.isPerfectBT && left.height == right.height) {  
  1471.             ret.isPerfectBT = true;  
  1472.         }  
  1473.           
  1474.         // set the isCompleteBT.  
  1475.         /* 
  1476.          * CompleteBinary Tree 的条件是: 
  1477.          *    1. 左右子树均为Perfect binary tree, 并且两者Height相同(其实就是本树是perfect tree) 
  1478.          *    2. 左子树为CompleteBinaryTree, 右子树为Perfect binary tree,并且两者Height差1 
  1479.          *    3. 左子树为Perfect Binary Tree,右子树为CompleteBinaryTree, 并且Height 相同 
  1480.          * */  
  1481.         ret.isCompleteBT = ret.isPerfectBT   
  1482.                 || (left.isCompleteBT && right.isPerfectBT && left.height == right.height + 1)  
  1483.                 || (left.isPerfectBT && right.isCompleteBT && left.height == right.height);  
  1484.           
  1485.         return ret;  
  1486.     }  
  1487.   
  1488.     /* 
  1489.      * 15. findLongest 
  1490.      * 第一种解法: 
  1491.      * 返回左边最长,右边最长,及左子树最长,右子树最长。 
  1492.      * */  
  1493.     public static int findLongest(TreeNode root) {  
  1494.         if (root == null) {  
  1495.             return -1;  
  1496.         }  
  1497.           
  1498.         TreeNode l = root;  
  1499.         int cntL = 0;  
  1500.         while (l.left != null) {  
  1501.             cntL++;  
  1502.             l = l.left;  
  1503.         }  
  1504.           
  1505.         TreeNode r = root;  
  1506.         int cntR = 0;  
  1507.         while (r.right != null) {  
  1508.             cntR++;  
  1509.             r = r.right;  
  1510.         }  
  1511.           
  1512.         int lmax = findLongest(root.left);  
  1513.         int rmax = findLongest(root.right);  
  1514.           
  1515.         int max = Math.max(lmax, rmax);  
  1516.         max = Math.max(max, cntR);  
  1517.         max = Math.max(max, cntL);  
  1518.           
  1519.         return max;  
  1520.     }  
  1521.       
  1522.     /*      1 
  1523.      *    2   3 
  1524.      *  3       4 
  1525.      *         6  1 
  1526.      *        7 
  1527.      *       9 
  1528.      *     11 
  1529.      *    2 
  1530.      *  14       
  1531.      * */  
  1532.     public static int findLongest2(TreeNode root) {  
  1533.         int [] maxVal = new int[1];  
  1534.         maxVal[0] = -1;  
  1535.         findLongest2Help(root, maxVal);  
  1536.         return maxVal[0];  
  1537.     }  
  1538.       
  1539.     // ret:  
  1540.     // 0: the left side longest,  
  1541.     // 1: the right side longest.  
  1542.     static int maxLen = -1;  
  1543.     static int[] findLongest2Help(TreeNode root, int[] maxVal) {  
  1544.         int[] ret = new int[2];  
  1545.         if (root == null) {  
  1546.             ret[0] = -1;  
  1547.             ret[1] = -1;  
  1548.             return ret;  
  1549.         }  
  1550.           
  1551.         ret[0] = findLongest2Help(root.left, maxVal)[0] + 1;  
  1552.         ret[1] = findLongest2Help(root.right, maxVal)[1] + 1;  
  1553.         //maxLen = Math.max(maxLen, ret[0]);  
  1554.         //maxLen = Math.max(maxLen, ret[1]);  
  1555.         maxVal[0] = Math.max(maxVal[0], ret[0]);  
  1556.         maxVal[0] = Math.max(maxVal[0], ret[1]);  
  1557.   
  1558.         return ret;  
  1559.     }  
  1560. }   
package Algorithms.tree;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Stack;


/**
 * REFS:  
 * http://blog.csdn.net/fightforyourdream/article/details/16843303 面试大总结之二:Java搞定面试中的二叉树题目
 * http://blog.csdn.net/luckyxiaoqiang/article/details/7518888          轻松搞定面试中的二叉树题目 
 * http://www.cnblogs.com/Jax/archive/2009/12/28/1633691.html           算法大全(3) 二叉树 
 *  
 * 1. 求二叉树中的节点个数: getNodeNumRec(递归),getNodeNum(迭代) 
 * 2. 求二叉树的深度: getDepthRec(递归),getDepth  
 * 3. 前序遍历,中序遍历,后序遍历: preorderTraversalRec, preorderTraversal, inorderTraversalRec, postorderTraversalRec 
 * (https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_2) 
 * 4.分层遍历二叉树(按层次从上往下,从左往右): levelTraversal, levelTraversalRec(递归解法) 
 * 5. 将二叉查找树变为有序的双向链表: convertBST2DLLRec, convertBST2DLL 
 * 6. 求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel
 * 7. 求二叉树中叶子节点的个数:getNodeNumLeafRec, getNodeNumLeaf 
 * 8. 判断两棵二叉树是否相同的树:isSameRec, isSame
 * 9. 判断二叉树是不是平衡二叉树:isAVLRec 
 * 10. 求二叉树的镜像(破坏和不破坏原来的树两种情况):
 *     mirrorRec, mirrorCopyRec
 *     mirror, mirrorCopy 
 * 10.1 判断两个树是否互相镜像:isMirrorRec isMirror
 * 11. 求二叉树中两个节点的最低公共祖先节点:
 *      LAC        求解最小公共祖先, 使用list来存储path.
 *      LCABstRec  递归求解BST树.
 *      LCARec     递归算法 .
 * 12. 求二叉树中节点的最大距离:getMaxDistanceRec 
 * 13. 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec
 * 14. 判断二叉树是不是完全二叉树:isCompleteBinaryTree, isCompleteBinaryTreeRec
 * 15. 找出二叉树中最长连续子串(即全部往左的连续节点,或是全部往右的连续节点)findLongest
 */  

public class TreeDemo {
    /* 
            1  
           / \  
          2   3  
         / \   \  
        4   5   6      
    */  
    public static void main(String[] args) {
        TreeNode r1 = new TreeNode(1);
        TreeNode r2 = new TreeNode(2);
        TreeNode r3 = new TreeNode(3);
        TreeNode r4 = new TreeNode(4);
        TreeNode r5 = new TreeNode(5);
        TreeNode r6 = new TreeNode(6);
        
/*                    
       10  
       / \  
      6   14  
     / \   \  
    4   8   16
   /
  0        
*/ 
        /* 
        1  
       / \  
      2   3  
     / \   \  
    4   5   6      
*/  
//        TreeNode r1 = new TreeNode(10);
//        TreeNode r2 = new TreeNode(6);
//        TreeNode r3 = new TreeNode(14);
//        TreeNode r4 = new TreeNode(4);
//        TreeNode r5 = new TreeNode(8);
//        TreeNode r6 = new TreeNode(16);
        
        TreeNode r7 = new TreeNode(0);
        
        r1.left = r2;
        r1.right = r3;
        r2.left = r4;
        r2.right = r5;
        r3.right = r6;
        
        r4.left = r7;

        TreeNode t1 = new TreeNode(10);
        TreeNode t2 = new TreeNode(6);
        TreeNode t3 = new TreeNode(14);
        TreeNode t4 = new TreeNode(4);
        TreeNode t5 = new TreeNode(8);
        TreeNode t6 = new TreeNode(16);
        
        TreeNode t7 = new TreeNode(0);
        
        TreeNode t8 = new TreeNode(0);
        TreeNode t9 = new TreeNode(0);
        TreeNode t10 = new TreeNode(0);
        TreeNode t11 = new TreeNode(0);
        
        
        t1.left = t2;
        t1.right = t3;
        t2.left = t4;
        t2.right = t5;
        t3.left = t6;
        t3.right = t7;
        
        t4.left = t8;
        //t4.right = t9;
        t5.right = t9;
        
        
        // test distance
//        t5.right = t8;
//        t8.right = t9;
//        t9.right = t10;
//        t10.right = t11;
        
        /* 
        10  
        / \  
       6   14  
      / \   \  
     4   8   16
    /
   0        
 */ 
//        System.out.println(LCABstRec(t1, t2, t4).val);
//        System.out.println(LCABstRec(t1, t2, t6).val);
//        System.out.println(LCABstRec(t1, t4, t6).val);
//        System.out.println(LCABstRec(t1, t4, t7).val);
//        System.out.println(LCABstRec(t1, t3, t6).val);
//        
//        System.out.println(LCA(t1, t2, t4).val);
//        System.out.println(LCA(t1, t2, t6).val);
//        System.out.println(LCA(t1, t4, t6).val);
//        System.out.println(LCA(t1, t4, t7).val);
//        System.out.println(LCA(t1, t3, t6).val);
//        System.out.println(LCA(t1, t6, t6).val);
        
        //System.out.println(getMaxDistanceRec(t1));
        
        //System.out.println(isSame(r1, t1));
        
//        System.out.println(isAVLRec(r1));
//        
//        preorderTraversalRec(r1);
//        //mirrorRec(r1);
//        //TreeNode r1Mirror = mirror(r1);
//        
//        TreeNode r1MirrorCopy = mirrorCopy(r1);
//        System.out.println();
//        //preorderTraversalRec(r1Mirror);
//        preorderTraversalRec(r1MirrorCopy);
//        
//        System.out.println();
//        
//        System.out.println(isMirrorRec(r1, r1MirrorCopy));
//        System.out.println(isMirror(r1, r1MirrorCopy));
        
        
        //System.out.println(getNodeNumKthLevelRec(r1, 5));
        
        //System.out.println(getNodeNumLeaf(r1));
        
//      System.out.println(getNodeNumRec(null));
//      System.out.println(getNodeNum(r1));
        //System.out.println(getDepthRec(null));
//        System.out.println(getDepth(r1));
//        
//        preorderTraversalRec(r1);
//        System.out.println();
//        preorderTraversal(r1);
//        System.out.println();
//        inorderTraversalRec(r1);
//        
//        System.out.println();
//          inorderTraversal(r1);
//        postorderTraversalRec(r1);
//        System.out.println();
//        postorderTraversal(r1);
//        System.out.println();
//        levelTraversal(r1);
//        
//        System.out.println();
//        levelTraversalRec(r1);
        
//        TreeNode ret = convertBST2DLLRec(r1);
//        while (ret != null) {
//            System.out.print(ret.val + " ");
//            ret = ret.right;
//        }
        
//        TreeNode ret2 = convertBST2DLL(r1);
//        while (ret2.right != null) {
//            ret2 = ret2.right;
//        }
//        
//        while (ret2 != null) {
//            System.out.print(ret2.val + " ");
//            ret2 = ret2.left;
//        }
//        
//        TreeNode ret = convertBST2DLL(r1);
//        while (ret != null) {
//            System.out.print(ret.val + " ");
//            ret = ret.right;
//        }
        
//        System.out.println();
//        System.out.println(findLongest(r1));
//        System.out.println();
//        System.out.println(findLongest2(r1));
        
        // test the rebuildBinaryTreeRec.
        //test_rebuildBinaryTreeRec();
        
        System.out.println(isCompleteBinaryTreeRec(t1));
        System.out.println(isCompleteBinaryTree(t1));
    }
    
    public static void test_rebuildBinaryTreeRec() {
        ArrayList list1 = new ArrayList();
        list1.add(1);
        list1.add(2);
        list1.add(4);
        list1.add(5);
        list1.add(3);
        list1.add(6);
        list1.add(7);
        list1.add(8);
        
        ArrayList list2 = new ArrayList();
        list2.add(4);
        list2.add(2);
        list2.add(5);
        list2.add(1);
        list2.add(3);
        list2.add(7);
        list2.add(6);
        list2.add(8);
        
        TreeNode root = rebuildBinaryTreeRec(list1, list2);
        preorderTraversalRec(root);
        System.out.println();
        postorderTraversalRec(root);
    }
    
    private static class TreeNode{
        int val;
        TreeNode left;
        TreeNode right;
        public TreeNode(int val){
            this.val = val;
            left = null;
            right = null;                    
        }
    }
    
    /*
     * null返回0,然后把左右子树的size加上即可。
     * */
    public static int getNodeNumRec(TreeNode root) {
        if (root == null) {
            return 0;
        }
                
        return getNodeNumRec(root.left) + getNodeNumRec(root.right) + 1;
    }

    /** 
     *  求二叉树中的节点个数迭代解法O(n):基本思想同LevelOrderTraversal, 
     *  即用一个Queue,在Java里面可以用LinkedList来模拟  
     */  
    public static int getNodeNum(TreeNode root) {
        if (root == null) {
            return 0;
        }
        
        Queue q = new LinkedList(); 
        q.offer(root);
        
        int cnt = 0;
        while (!q.isEmpty()) {
            TreeNode node = q.poll();
            if (node.left != null) {
                q.offer(node.left);
            }
            
            if (node.right != null) {
                q.offer(node.right);
            }
            
            cnt++;
        }
        
        return cnt;
    }
    
    public static int getDepthRec(TreeNode root) {
        if (root == null) {
            return -1;
        }
        
        return Math.max(getDepthRec(root.left), getDepthRec(root.right)) + 1;
    }
    
    /*
     * 可以用 level LevelOrderTraversal 来实现,我们用一个dummyNode来分隔不同的层,这样即可计算出实际的depth.
     *      1  
           / \  
          2   3  
         / \   \  
        4   5   6
     * 
     * 在队列中如此排列: 1, dummy, 2, 3, dummy, 4, 5, 5, dummy  
     * 
    */  
    public static int getDepth(TreeNode root) {
        if (root == null) {
            return 0;
        }
        
        TreeNode dummy = new TreeNode(0);
        Queue q = new LinkedList();
        q.offer(root);
        q.offer(dummy);
        
        int depth = -1;
        while (!q.isEmpty()) {
            TreeNode curr = q.poll();
            if (curr == dummy) {
                depth++;
                if (!q.isEmpty()) {  // 使用DummyNode来区分不同的层, 如果下一层不是为空,则应该在尾部加DummyNode.
                    q.offer(dummy);
                }
            }
            
            if (curr.left != null) {
                q.offer(curr.left);
            }
            if (curr.right != null) {
                q.offer(curr.right);
            }
        }
        
        return depth;
    }
    
    /*
     * 3. 前序遍历,中序遍历,后序遍历: preorderTraversalRec, preorderTraversal, inorderTraversalRec, postorderTraversalRec 
     * (https://en.wikipedia.org/wiki/Tree_traversal#Pre-order_2)
     * */
    public static void preorderTraversalRec(TreeNode root) {
        if (root == null) {
            return;
        }
        
        System.out.print(root.val + " ");
        preorderTraversalRec(root.left);
        preorderTraversalRec(root.right);
    }
    
    /*
     * 前序遍历,Iteration 算法. 把根节点存在stack中。
     * */
    public static void preorderTraversal(TreeNode root) {
        if (root == null) {
            return;
        }
        
        Stack s = new Stack();
        s.push(root);
        
        while (!s.isEmpty()) {
            TreeNode node = s.pop();
            System.out.print(node.val + " ");
            if (node.right != null) { //
                s.push(node.right);
            }
            
            // 我们需要先压入右节点,再压入左节点,这样就可以先弹出左节点。 
            if (node.left != null) {
                s.push(node.left);
            }                       
        }
    }
    
    /*
     * 中序遍历
     * */
    public static void inorderTraversalRec(TreeNode root) {
        if (root == null) {
            return;
        }
        
        inorderTraversalRec(root.left);
        System.out.print(root.val + " ");
        inorderTraversalRec(root.right);
    }
    
    /** 
     * 中序遍历迭代解法 ,用栈先把根节点的所有左孩子都添加到栈内, 
     * 然后输出栈顶元素,再处理栈顶元素的右子树 
     * http://www.youtube.com/watch?v=50v1sJkjxoc 
     *  
     * 还有一种方法能不用递归和栈,基于线索二叉树的方法,较麻烦以后补上 
     * http://www.geeksforgeeks.org/inorder-tree-traversal-without-recursion-and-without-stack/ 
     */  
    public static void inorderTraversal(TreeNode root) {
        if (root == null) {
            return;
        }
        
        Stack s = new Stack();
        
        TreeNode cur = root;
        
        while(true) {
            // 把当前节点的左节点都push到栈中.
            while (cur != null) {
                s.push(cur);
                cur = cur.left;
            }
            
            if (s.isEmpty()) {
                break;
            }
            
            // 因为此时已经没有左孩子了,所以输出栈顶元素 
            cur = s.pop();
            System.out.print(cur.val + " ");
            
            // 准备处理右子树  
            cur = cur.right;            
        }
    }
    
    // 后序遍历
    /*
     *      1  
           / \  
          2   3  
         / \   \  
        4   5   6
        
        if put into the stack directly, then it should be:
        1, 2, 4, 5, 3, 6 in the stack.
        when pop, it should be: 6, 3, 5, 4, 2, 1
        
        if I 
     * */
    
    public static void postorderTraversalRec(TreeNode root) {
        if (root == null) {
            return;
        }
        
        postorderTraversalRec(root.left);
        postorderTraversalRec(root.right);
        System.out.print(root.val + " ");
    }
    
    /** 
     *  后序遍历迭代解法 
     *  http://www.youtube.com/watch?v=hv-mJUs5mvU 
     *  http://blog.csdn.net/tang_jin2015/article/details/8545457
     *  从左到右的后序 与从右到左的前序的逆序是一样的,所以就简单喽! 哈哈
     *  用另外一个栈进行翻转即可喽 
     */ 
    public static void postorderTraversal(TreeNode root) {
        if (root == null) {
            return;
        }
        
        Stack s = new Stack();
        Stack out = new Stack();
        
        s.push(root);
        while(!s.isEmpty()) {
            TreeNode cur = s.pop();
            out.push(cur);
            
            if (cur.left != null) {
                s.push(cur.left);
            }
            if (cur.right != null) {
                s.push(cur.right);
            }
        }
        
        while(!out.isEmpty()) {
            System.out.print(out.pop().val + " ");
        }
    }
    
    /*
     * 分层遍历二叉树(按层次从上往下,从左往右)迭代 
     * 其实就是广度优先搜索,使用队列实现。队列初始化,将根节点压入队列。当队列不为空,进行如下操作:弹出一个节点 
     * ,访问,若左子节点或右子节点不为空,将其压入队列 
     * */
    public static void levelTraversal(TreeNode root) {
        if (root == null) {
            return;
        }
        
        Queue q = new LinkedList();
        q.offer(root);
        
        while (!q.isEmpty()) {
            TreeNode cur = q.poll();
            
            System.out.print(cur.val + " ");
            if (cur.left != null) {
                q.offer(cur.left);
            }
            if (cur.right != null) {
                q.offer(cur.right);
            }
        }
    }
    
    public static void levelTraversalRec(TreeNode root) {
        ArrayList> ret = new ArrayList>();
        levelTraversalVisit(root, 0, ret);
        System.out.println(ret);
    }
    
    /** 
     *  分层遍历二叉树(递归) 
     *  很少有人会用递归去做level traversal 
     *  基本思想是用一个大的ArrayList,里面包含了每一层的ArrayList。 
     *  大的ArrayList的size和level有关系 
     *   
     *  http://discuss.leetcode.com/questions/49/binary-tree-level-order-traversal#answer-container-2543 
     */  
    public static void levelTraversalVisit(TreeNode root, int level, ArrayList> ret) {
        if (root == null) {
            return;
        }
        
        // 如果ArrayList的层数不够用, 则新添加一层
        // when size = 3, level: 0, 1, 2
        if (level >= ret.size()) {
            ret.add(new ArrayList());
        }
        
        // visit 当前节点
        ret.get(level).add(root.val);
        
        // 将左子树, 右子树添加到对应的层。
        levelTraversalVisit(root.left, level + 1, ret);
        levelTraversalVisit(root.right, level + 1, ret);
    }
    
    /*
     * 题目要求:将二叉查找树转换成排序的双向链表,不能创建新节点,只调整指针。
       查找树的结点定义如下:
       既然是树,其定义本身就是递归的,自然用递归算法处理就很容易。将根结点的左子树和右子树转换为有序的双向链表,
       然后根节点的left指针指向左子树结果的最后一个结点,同时左子树最后一个结点的right指针指向根节点;
       根节点的right指针指向右子树结果的第一个结点,
       同时右子树第一个结点的left指针指向根节点。
     * */
    public static TreeNode convertBST2DLLRec(TreeNode root) {
        return convertBST2DLLRecHelp(root)[0];
    }
    
    /*
     * ret[0] 代表左指针
     * ret[1] 代表右指针
     * */
    public static TreeNode[] convertBST2DLLRecHelp(TreeNode root) {
        TreeNode[] ret = new TreeNode[2];
        ret[0] = null;
        ret[1] = null;
                
        if (root == null) {
            return ret;
        }
        
        if (root.left != null) {
            TreeNode left[] = convertBST2DLLRecHelp(root.left);
            left[1].right = root;  // 将左子树的尾节点连接到根
            root.left = left[1];
            
            ret[0] = left[0];
        } else {
            ret[0] = root;   // 左节点返回root.
        }
        
        if (root.right != null) {
            TreeNode right[] = convertBST2DLLRecHelp(root.right);
            right[0].left = root;  // 将右子树的头节点连接到根
            root.right = right[0];
            
            ret[1] = right[1];
        } else {
            ret[1] = root;  // 右节点返回root.
        }
        
        return ret;
    }
    
    /** 
     * 将二叉查找树变为有序的双向链表 迭代解法 
     * 类似inOrder traversal的做法 
     */  
    public static TreeNode convertBST2DLL(TreeNode root) {
        while (root == null) {
            return null;
        }
        
        TreeNode pre = null;
        Stack s = new Stack();
        TreeNode cur = root;
        TreeNode head = null;       // 链表头
        
        while (true) {
            while (cur != null) {
                s.push(cur);
                cur = cur.left;
            }
            
            // if stack is empty, just break;
            if (s.isEmpty()) {
                break;
            }
            
            cur = s.pop(); 
            if (head == null) {
                head = cur;
            }

            // link pre and cur.
            cur.left = pre;
            if (pre != null) {
                pre.right = cur;
            }
            
            // 左节点已经处理完了,处理右节点
            cur = cur.right;
            pre = cur;
        }
        
        return root;
    }

/*
 *  * 6. 求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel 
 * */
    public static int getNodeNumKthLevel(TreeNode root, int k) {
        if (root == null || k <= 0) {
            return 0;
        }
        
        int level = 0;
        
        Queue q = new LinkedList();
        q.offer(root);
        
        TreeNode dummy = new TreeNode(0);
        int cnt = 0; // record the size of the level.
        
        q.offer(dummy);
        while (!q.isEmpty()) {
            TreeNode node = q.poll();
            
            if (node == dummy) {
                level++;
                if (level == k) {
                    return cnt;
                }
                cnt = 0; // reset the cnt;
                if (q.isEmpty()) {
                    break;
                }
                q.offer(dummy);
                continue;
            }
            
            cnt++;
            if (node.left != null) {
                q.offer(node.left);
            }
            
            if (node.right != null) {
                q.offer(node.right);
            }
        }
        
        return 0;
    }
    
    /*
     *  * 6. 求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel 
     * */
    public static int getNodeNumKthLevelRec(TreeNode root, int k) {
        if (root == null || k <= 0) {
            return 0;
        }
        
        if (k == 1) {
            return 1;
        }
        
        // 将左子树及右子树在K层的节点个数相加.
        return getNodeNumKthLevelRec(root.left, k - 1) + getNodeNumKthLevelRec(root.right, k - 1);
    }
    
    /*
     * 7. getNodeNumLeafRec  把左子树和右子树的叶子节点加在一起即可
     * */
    public static int getNodeNumLeafRec(TreeNode root) {
        if (root == null) {
            return 0;
        }
        
        if (root.left == null && root.right == null) {
            return 1;
        }
        
        return getNodeNumLeafRec(root.left) + getNodeNumLeafRec(root.right);
    }
    
    /* 7. getNodeNumLeaf
     * 随便使用一种遍历方法都可以,比如,中序遍历。
     * inorderTraversal,判断是不是叶子节点。
     * */
    public static int getNodeNumLeaf(TreeNode root) {
        if (root == null) {
            return 0;
        }
        
        int cnt = 0;
        
        // we can use inorderTraversal travesal to do it.
        Stack s = new Stack();
        TreeNode cur = root;
        
        while (true) {
            while (cur != null) {
                s.push(cur);
                cur = cur.left;
            }
            
            if (s.isEmpty()) {
                break;
            }
            
            // all the left child has been put into the stack, let's deal with the 
            // current node.
            cur = s.pop();
            if (cur.left == null && cur.right == null) {
                cnt++;
            }
            cur = cur.right;
        }
        
        return cnt;
    }
    
    /*
     * 8. 判断两棵二叉树是否相同的树。 
     * 递归解法:  
     * (1)如果两棵二叉树都为空,返回真 
     * (2)如果两棵二叉树一棵为空,另一棵不为空,返回假  
     * (3)如果两棵二叉树都不为空,如果对应的左子树和右子树都同构返回真,其他返回假 
     * */
    public static boolean isSameRec(TreeNode r1, TreeNode r2) {
        // both are null.
        if (r1 == null && r2 == null) {
            return true;
        }
        
        // one is null.
        if (r1 == null || r2 == null) {
            return false;
        }
        
        // 1. the value of the root should be the same;
        // 2. the left tree should be the same.
        // 3. the right tree should be the same.
        return r1.val == r2.val && 
                isSameRec(r1.left, r2.left) && isSameRec(r1.right, r2.right);
    }
    
    /*
     * 8. 判断两棵二叉树是否相同的树。
     * 迭代解法 
     * 我们直接用中序遍历来比较就好啦 
     * */
    public static boolean isSame(TreeNode r1, TreeNode r2) {
        // both are null.
        if (r1 == null && r2 == null) {
            return true;
        }
        
        // one is null.
        if (r1 == null || r2 == null) {
            return false;
        }
        
        Stack s1 = new Stack();
        Stack s2 = new Stack();
        
        TreeNode cur1 = r1;
        TreeNode cur2 = r2;
        
        while (true) {
            while (cur1 != null && cur2 != null) {
                s1.push(cur1);
                s2.push(cur2);
                cur1 = cur1.left;
                cur2 = cur2.left;
            }
            
            if (cur1 != null || cur2 != null) {
                return false;
            }
            
            if (s1.isEmpty() && s2.isEmpty()) {
                break;
            }
            
            cur1 = s1.pop();
            cur2 = s2.pop();
            if (cur1.val != cur2.val) {
                return false;
            }
            
            cur1 = cur1.right;
            cur2 = cur2.right;
        }
        
        return true;
    }
    
/*
 * 
 *  9. 判断二叉树是不是平衡二叉树:isAVLRec
 *     1. 左子树,右子树的高度差不能超过1
 *     2. 左子树,右子树都是平衡二叉树。 
 *      
 */
    public static boolean isAVLRec(TreeNode root) {
        if (root == null) {
            return true;
        }
        
        // 左子树,右子树都必须是平衡二叉树。 
        if (!isAVLRec(root.left) || !isAVLRec(root.right)) {
            return false;
        }
        
        int dif = Math.abs(getDepthRec(root.left) - getDepthRec(root.right));
        if (dif > 1) {
            return false;
        }
        
        return true;
    }
    
    /** 
     * 10. 求二叉树的镜像 递归解法:
     * 
     *   (1) 破坏原来的树
     *   
     *      1               1
     *     /                 \
     *    2     ----->        2
     *     \                 /
     *      3               3
     * */  
    public static TreeNode mirrorRec(TreeNode root) {  
        if (root == null) {
            return null;
        }
        
        // 先把左右子树分别镜像,并且交换它们
        TreeNode tmp = root.right;
        root.right = mirrorRec(root.left);
        root.left = mirrorRec(tmp);
        
        return root;
    }  
    
    /** 
     * 10. 求二叉树的镜像 Iterator解法:
     * 
     *   (1) 破坏原来的树
     *   
     *      1               1
     *     /                 \
     *    2     ----->        2
     *     \                 /
     *      3               3
     *      
     *  应该可以使用任何一种Traversal 方法。 
     *  我们现在可以试看看使用最简单的前序遍历。
     * */  
    public static TreeNode mirror(TreeNode root) {  
        if (root == null) {
            return null;
        }
        
        Stack s = new Stack();
        s.push(root);
        
        while (!s.isEmpty()) {
            TreeNode cur = s.pop();
            
            // 交换当前节点的左右节点
            TreeNode tmp = cur.left;
            cur.left = cur.right;
            cur.right = tmp;
            
            // traversal 左节点,右节点。
            if (cur.right != null) {
                s.push(cur.right);
            }
            
            if (cur.left != null) {
                s.push(cur.left);
            }
        }
        
        return root;
    }  
    
    /** 
     * 10. 求二叉树的镜像 Iterator解法:
     * 
     *   (2) 创建一个新的树
     *   
     *      1               1
     *     /                 \
     *    2     ----->        2
     *     \                 /
     *      3               3
     *      
     *  应该可以使用任何一种Traversal 方法。 
     *  我们现在可以试看看使用最简单的前序遍历。
     *  前序遍历我们可以立刻把新建好的左右节点创建出来,比较方便 
     * */  
    public static TreeNode mirrorCopy(TreeNode root) {  
        if (root == null) {
            return null;
        }
        
        Stack s = new Stack();
        Stack sCopy = new Stack();
        s.push(root);
        
        TreeNode rootCopy = new TreeNode(root.val);
        sCopy.push(rootCopy);
        
        while (!s.isEmpty()) {
            TreeNode cur = s.pop();
            TreeNode curCopy = sCopy.pop();
            
            // traversal 左节点,右节点。
            if (cur.right != null) {
                
                // copy 在这里做比较好,因为我们可以容易地找到它的父节点
                TreeNode leftCopy = new TreeNode(cur.right.val);
                curCopy.left = leftCopy;
                s.push(cur.right);
                sCopy.push(curCopy.left);
            }
            
            if (cur.left != null) {
                // copy 在这里做比较好,因为我们可以容易地找到它的父节点
                TreeNode rightCopy = new TreeNode(cur.left.val);
                curCopy.right = rightCopy;
                s.push(cur.left);
                sCopy.push(curCopy.right);
            }
        }
        
        return rootCopy;
    }  
    
    /** 
     * 10. 求二叉树的镜像 递归解法:
     * 
     *   (1) 不破坏原来的树,新建一个树 
     *   
     *      1               1
     *     /                 \
     *    2     ----->        2
     *     \                 /
     *      3               3
     * */  
    public static TreeNode mirrorCopyRec(TreeNode root) {  
        if (root == null) {
            return null;
        }
        
        // 先把左右子树分别镜像,并且把它们连接到新建的root节点。
        TreeNode rootCopy = new TreeNode(root.val);
        rootCopy.left = mirrorCopyRec(root.right);
        rootCopy.right = mirrorCopyRec(root.left);
        
        return rootCopy;
    }  
    
    /*
     * 10.1. 判断两个树是否互相镜像
     *  (1) 根必须同时为空,或是同时不为空
     * 
     * 如果根不为空:
     *  (1).根的值一样
     *  (2).r1的左树是r2的右树的镜像
     *  (3).r1的右树是r2的左树的镜像  
     * */
    public static boolean isMirrorRec(TreeNode r1, TreeNode r2){  
        // 如果2个树都是空树
        if (r1 == null && r2 == null) {
            return true;
        }
        
        // 如果其中一个为空,则返回false.
        if (r1 == null || r2 == null) {
            return false;
        }
        
        // If both are not null, they should be:
        // 1. have same value for root.
        // 2. R1's left tree is the mirror of R2's right tree;
        // 3. R2's right tree is the mirror of R1's left tree;
        return r1.val == r2.val 
                && isMirrorRec(r1.left, r2.right)
                && isMirrorRec(r1.right, r2.left);
    }
    
    /*
     * 10.1. 判断两个树是否互相镜像 Iterator 做法
     *  (1) 根必须同时为空,或是同时不为空
     * 
     * 如果根不为空:
     * traversal 整个树,判断它们是不是镜像,每次都按照反向来traversal  
     * (1). 当前节点的值相等
     * (2). 当前节点的左右节点要镜像,
     *    无论是左节点,还是右节点,对应另外一棵树的镜像位置,可以同时为空,或是同时不为空,但是不可以一个为空,一个不为空。      
     * */
    public static boolean isMirror(TreeNode r1, TreeNode r2){  
        // 如果2个树都是空树
        if (r1 == null && r2 == null) {
            return true;
        }
        
        // 如果其中一个为空,则返回false.
        if (r1 == null || r2 == null) {
            return false;
        }
        
        Stack s1 = new Stack();
        Stack s2 = new Stack();
        
        s1.push(r1);
        s2.push(r2);
        
        while (!s1.isEmpty() && !s2.isEmpty()) {
            TreeNode cur1 = s1.pop();
            TreeNode cur2 = s2.pop();
            
            // 弹出的节点的值必须相等 
            if (cur1.val != cur2.val) {
                return false;
            }
            
            // tree1的左节点,tree2的右节点,可以同时不为空,也可以同时为空,否则返回false.
            TreeNode left1 = cur1.left;
            TreeNode right1 = cur1.right;
            TreeNode left2 = cur2.left;
            TreeNode right2 = cur2.right;
            
            if (left1 != null && right2 != null) {
                s1.push(left1);
                s2.push(right2);
            } else if (!(left1 == null && right2 == null)) {
                return false;
            }
            
            // tree1的左节点,tree2的右节点,可以同时不为空,也可以同时为空,否则返回false.
            if (right1 != null && left2 != null) {
                s1.push(right1);
                s2.push(left2);
            } else if (!(right1 == null && left2 == null)) {
                return false;
            }
        }
        
        return true;
    }  
    
    /*
     * 11. 求二叉树中两个节点的最低公共祖先节点:
     * Recursion Version:
     * LACRec 
     * 1. If found in the left tree, return the Ancestor.
     * 2. If found in the right tree, return the Ancestor.
     * 3. If Didn't find any of the node, return null.
     * 4. If found both in the left and the right tree, return the root.
     * */
    public static TreeNode LACRec(TreeNode root, TreeNode node1, TreeNode node2) {
        if (root == null || node1 == null || node2 == null) {
            return null;
        }
        
        // If any of the node is the root, just return the root.
        if (root == node1 || root == node2) {
            return root;
        }
        
        // if no node is in the node, just recursively find it in LEFT and RIGHT tree.
        TreeNode left = LACRec(root.left, node1, node2);
        TreeNode right = LACRec(root.right, node1, node2);
        
        if (left == null) {  // If didn't found in the left tree, then just return it from right.
            return right;
        } else if (right == null) { // Or if didn't found in the right tree, then just return it from the left side.
            return left;
        } 
        
        // if both right and right found a node, just return the root as the Common Ancestor.
        return root;
    }
    
    /*
     * 11. 求BST中两个节点的最低公共祖先节点:
     * Recursive version:
     * LCABst 
     * 
     * 1. If found in the left tree, return the Ancestor.
     * 2. If found in the right tree, return the Ancestor.
     * 3. If Didn't find any of the node, return null.
     * 4. If found both in the left and the right tree, return the root.
     * */
    public static TreeNode LCABstRec(TreeNode root, TreeNode node1, TreeNode node2) {
        if (root == null || node1 == null || node2 == null) {
            return null;
        }
        
        // If any of the node is the root, just return the root.
        if (root == node1 || root == node2) {
            return root;
        }
        
        int min = Math.min(node1.val, node2.val);
        int max = Math.max(node1.val, node2.val);
        
        // if the values are smaller than the root value, just search them in the left tree.
        if (root.val > max) {
            return LCABstRec(root.left, node1, node2);
        } else if (root.val < min) {
        // if the values are larger than the root value, just search them in the right tree.    
            return LCABstRec(root.right, node1, node2);
        }
        
        // if root is in the middle, just return the root.
        return root;
    }
    
    /*
     * 解法1. 记录下path,并且比较之:
     * LAC
     * http://www.geeksforgeeks.org/lowest-common-ancestor-binary-tree-set-1/
     * */
    public static TreeNode LCA(TreeNode root, TreeNode r1, TreeNode r2) {
        // If the nodes have one in the root, just return the root.
        if (root == null || r1 == null || r2 == null) {
            return null;
        }
        
        ArrayList list1 = new ArrayList();
        ArrayList list2 = new ArrayList();
        
        boolean find1 = LCAPath(root, r1, list1);
        boolean find2 = LCAPath(root, r2, list2);
        
        // If didn't find any of the node, just return a null.
        if (!find1 || !find2) {
            return null;
        }
        
        // 注意: 使用Iterator 对于linkedlist可以提高性能。
        // 所以 统一使用Iterator 来进行操作。
        Iterator iter1 = list1.iterator();
        Iterator iter2 = list2.iterator();
        
        TreeNode last = null;
        while (iter1.hasNext() && iter2.hasNext()) {
            TreeNode tmp1 = iter1.next();
            TreeNode tmp2 = iter2.next();
            
            if (tmp1 != tmp2) {
                return last;
            }
            
            last = tmp1;
        }
        
        // If never find any node which is different, means Node 1 and Node 2 are the same one.
        // so just return the last one.
        return last;
    }
    
    public static boolean LCAPath(TreeNode root, TreeNode node, ArrayList path) {
        // if didn't find, we should return a empty path.
        if (root == null || node == null) {
            return false;
        }
        
        // First add the root node.
        path.add(root);
        
        // if the node is in the left side.
        if (root != node 
                && !LCAPath(root.left, node, path)
                && !LCAPath(root.right, node, path)
                ) {
            // Didn't find the node. should remove the node added before.
            path.remove(root);
            return false;
        }
        
        // found
        return true;
    }
    
    /*
     *  * 12. 求二叉树中节点的最大距离:getMaxDistanceRec
     *  
     *  首先我们来定义这个距离:
     *  距离定义为:两个节点间边的数目.
     *  如:
     *     1
     *    / \
     *   2   3
     *        \
     *         4
     *   这里最大距离定义为2,4的距离,为3.      
     * 求二叉树中节点的最大距离 即二叉树中相距最远的两个节点之间的距离。 (distance / diameter) 
     * 递归解法:
     * 返回值设计:
     * 返回1. 深度, 2. 当前树的最长距离  
     * (1) 计算左子树的深度,右子树深度,左子树独立的链条长度,右子树独立的链条长度
     * (2) 最大长度为三者之最:
     *    a. 通过根节点的链,为左右深度+2
     *    b. 左子树独立链
     *    c. 右子树独立链。
     * 
     * (3)递归初始条件:
     *   当root == null, depth = -1.maxDistance = -1;
     *   
     */  
    public static int getMaxDistanceRec(TreeNode root) {
        return getMaxDistanceRecHelp(root).maxDistance;
    }
    
    public static Result getMaxDistanceRecHelp(TreeNode root) {
        Result ret = new Result(-1, -1);
        
        if (root == null) {
            return ret;
        }
        
        Result left = getMaxDistanceRecHelp(root.left);
        Result right = getMaxDistanceRecHelp(root.right);
        
        // 深度应加1, the depth from the subtree to the root.
        ret.depth = Math.max(left.depth, right.depth) + 1;
        
        // 左子树,右子树与根的距离都要加1,所以通过根节点的路径为两边深度+2
        int crossLen = left.depth + right.depth + 2;
        
        // 求出cross根的路径,及左右子树的独立路径,这三者路径的最大值。
        ret.maxDistance = Math.max(left.maxDistance, right.maxDistance);
        ret.maxDistance = Math.max(ret.maxDistance, crossLen);
        
        return ret;
    }

    
    private static class Result {
        int depth;
        int maxDistance;
        public Result(int depth, int maxDistance) {
            this.depth = depth;
            this.maxDistance = maxDistance;
        }
    }
    
    /*
     *  13. 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec 
     *  We assume that there is no duplicate in the trees.
     *  For example:
     *          1
     *         / \
     *        2   3
     *       /\    \
     *      4  5    6
     *              /\
     *             7  8  
     *             
     *  PreOrder should be: 1   2 4 5   3 6 7 8
     *                      根   左子树    右子树  
     *  InOrder should be:  4 2 5   1   3 7 6 8
     *                       左子树  根  右子树
     * */                   
    public static TreeNode rebuildBinaryTreeRec(List preOrder, List inOrder) {
        if (preOrder == null || inOrder == null) {
            return null;
        }
        
        // If the traversal is empty, just return a NULL.
        if (preOrder.size() == 0 || inOrder.size() == 0) {
            return null;
        }
        
        // we can get the root from the preOrder. 
        // Because the first one is the root.
        // So we just create the root node here.
        TreeNode root = new TreeNode(preOrder.get(0));
        
        List preOrderLeft;
        List preOrderRight;
        List inOrderLeft;
        List inOrderRight;
        
        // 获得在 inOrder中,根的位置
        int rootInIndex = inOrder.indexOf(preOrder.get(0));
        preOrderLeft = preOrder.subList(1, rootInIndex + 1);
        preOrderRight = preOrder.subList(rootInIndex + 1, preOrder.size());
        
        // 得到inOrder左边的左子树
        inOrderLeft = inOrder.subList(0, rootInIndex);
        inOrderRight = inOrder.subList(rootInIndex + 1, inOrder.size());

        // 通过 Rec 来调用生成左右子树。
        root.left = rebuildBinaryTreeRec(preOrderLeft, inOrderLeft);
        root.right = rebuildBinaryTreeRec(preOrderRight, inOrderRight);
        
        return root;        
    }
    
    /*
     * 14. 判断二叉树是不是完全二叉树:isCompleteBinaryTree, isCompleteBinaryTreeRec
     * 进行level traversal, 一旦遇到一个节点的左节点为空,后面的节点的子节点都必须为空。而且不应该有下一行,其实就是队列中所有的
     * 元素都不应该再有子元素。
     * */
    
    public static boolean isCompleteBinaryTree(TreeNode root) {
        if (root == null) {
            return false;
        }
        
        TreeNode dummyNode = new TreeNode(0);
        Queue q = new LinkedList();
        
        q.offer(root);
        q.offer(dummyNode);
        
        // if this is true, no node should have any child.
        boolean noChild = false;
        
        while (!q.isEmpty()) {
            TreeNode cur = q.poll();
            if (cur == dummyNode) {
                if (!q.isEmpty()) {
                    q.offer(dummyNode);
                }
                // Dummy node不需要处理。 
                continue;
            }
            
            if (cur.left != null) {
                // 如果标记被设置,则Queue中任何元素不应再有子元素。
                if (noChild) {
                    return false;
                }
                q.offer(cur.left);
            } else {
                // 一旦某元素没有左节点或是右节点,则之后所有的元素都不应有子元素。
                // 并且该元素不可以有右节点.
                noChild = true;
            }
            
            if (cur.right != null) {
                // 如果标记被设置,则Queue中任何元素不应再有子元素。
                if (noChild) {
                    return false;
                }
                q.offer(cur.right);
            } else {
                // 一旦某元素没有左节点或是右节点,则之后所有的元素都不应有子元素。
                noChild = true;
            }
        }
        
        return true;
    }
    
    /*
     * 14. 判断二叉树是不是完全二叉树:isCompleteBinaryTreeRec
     * 
     * 
     *    我们可以分解为:
     *    CompleteBinary Tree 的条件是:
     *    1. 左右子树均为Perfect binary tree, 并且两者Height相同
     *    2. 左子树为CompleteBinaryTree, 右子树为Perfect binary tree,并且两者Height差1
     *    3. 左子树为Perfect Binary Tree,右子树为CompleteBinaryTree, 并且Height 相同
     *    
     *    Base 条件:
     *    (1) root = null: 为perfect & complete BinaryTree, Height -1;
     *    
     *    而 Perfect Binary Tree的条件:
     *    左右子树均为Perfect Binary Tree,并且Height 相同。
     * */
    
    public static boolean isCompleteBinaryTreeRec(TreeNode root) {
        return isCompleteBinaryTreeRecHelp(root).isCompleteBT;
    }
    
    private static class ReturnBinaryTree {
        boolean isCompleteBT;
        boolean isPerfectBT;
        int height;
        
        ReturnBinaryTree(boolean isCompleteBT, boolean isPerfectBT, int height) {
            this.isCompleteBT = isCompleteBT;
            this.isPerfectBT = isPerfectBT;
            this.height = height;
        }
    }
    
    /*
     * 我们可以分解为:
     *    CompleteBinary Tree 的条件是:
     *    1. 左右子树均为Perfect binary tree, 并且两者Height相同
     *    2. 左子树为CompleteBinaryTree, 右子树为Perfect binary tree,并且两者Height差1
     *    3. 左子树为Perfect Binary Tree,右子树为CompleteBinaryTree, 并且Height 相同
     *    
     *    Base 条件:
     *    (1) root = null: 为perfect & complete BinaryTree, Height -1;
     *    
     *    而 Perfect Binary Tree的条件:
     *    左右子树均为Perfect Binary Tree,并且Height 相同。
     * */
    public static ReturnBinaryTree isCompleteBinaryTreeRecHelp(TreeNode root) {
        ReturnBinaryTree ret = new ReturnBinaryTree(true, true, -1);
        
        if (root == null) {
            return ret;
        }
        
        ReturnBinaryTree left = isCompleteBinaryTreeRecHelp(root.left);
        ReturnBinaryTree right = isCompleteBinaryTreeRecHelp(root.right);
        
        // 树的高度为左树高度,右树高度的最大值+1
        ret.height = 1 + Math.max(left.height, right.height);
        
        // set the isPerfectBT
        ret.isPerfectBT = false;
        if (left.isPerfectBT && right.isPerfectBT && left.height == right.height) {
            ret.isPerfectBT = true;
        }
        
        // set the isCompleteBT.
        /*
         * CompleteBinary Tree 的条件是:
         *    1. 左右子树均为Perfect binary tree, 并且两者Height相同(其实就是本树是perfect tree)
         *    2. 左子树为CompleteBinaryTree, 右子树为Perfect binary tree,并且两者Height差1
         *    3. 左子树为Perfect Binary Tree,右子树为CompleteBinaryTree, 并且Height 相同
         * */
        ret.isCompleteBT = ret.isPerfectBT 
                || (left.isCompleteBT && right.isPerfectBT && left.height == right.height + 1)
                || (left.isPerfectBT && right.isCompleteBT && left.height == right.height);
        
        return ret;
    }

    /*
     * 15. findLongest
     * 第一种解法:
     * 返回左边最长,右边最长,及左子树最长,右子树最长。
     * */
    public static int findLongest(TreeNode root) {
        if (root == null) {
            return -1;
        }
        
        TreeNode l = root;
        int cntL = 0;
        while (l.left != null) {
            cntL++;
            l = l.left;
        }
        
        TreeNode r = root;
        int cntR = 0;
        while (r.right != null) {
            cntR++;
            r = r.right;
        }
        
        int lmax = findLongest(root.left);
        int rmax = findLongest(root.right);
        
        int max = Math.max(lmax, rmax);
        max = Math.max(max, cntR);
        max = Math.max(max, cntL);
        
        return max;
    }
    
    /*      1
     *    2   3
     *  3       4
     *         6  1
     *        7
     *       9
     *     11
     *    2
     *  14      
     * */
    public static int findLongest2(TreeNode root) {
        int [] maxVal = new int[1];
        maxVal[0] = -1;
        findLongest2Help(root, maxVal);
        return maxVal[0];
    }
    
    // ret:
    // 0: the left side longest,
    // 1: the right side longest.
    static int maxLen = -1;
    static int[] findLongest2Help(TreeNode root, int[] maxVal) {
        int[] ret = new int[2];
        if (root == null) {
            ret[0] = -1;
            ret[1] = -1;
            return ret;
        }
        
        ret[0] = findLongest2Help(root.left, maxVal)[0] + 1;
        ret[1] = findLongest2Help(root.right, maxVal)[1] + 1;
        //maxLen = Math.max(maxLen, ret[0]);
        //maxLen = Math.max(maxLen, ret[1]);
        maxVal[0] = Math.max(maxVal[0], ret[0]);
        maxVal[0] = Math.max(maxVal[0], ret[1]);

        return ret;
    }
} 


转 http://blog.sina.com.cn/s/blog_eb52001d0102v1si.html

0
0
 
 

我的同类文章

数据结构(6) 算法(18)
http://blog.csdn.net
  • 二叉树的常见问题及其解决程序2014-09-29阅读775
  • list和vector有什么区别?2014-08-07阅读445
  • 教你透彻了解红黑树2014-08-02阅读564
  • hash_set哈希集合容器2014-08-11阅读510
  • 经典面试题:设计包含min函数的栈,O(1)空间实现方法2014-08-07阅读416
  • 找工作知识储备(3)---从头说12种排序算法:原理、图解、动画视频演示、代码以及笔试面试题目中的应用2014-07-27阅读3186

你可能感兴趣的:(算法和数据结构)