面试大总结之二:Java搞定面试中的二叉树题目(七)

2014-11-24 08:29:22 · 作者: · 浏览: 11
/03/15/rebuild-a-binary-tree-from-inorder-and-preorder-traversals/ * 文中还提到一种避免开额外空间的方法,等下次补上 */ public static TreeNode rebuildBinaryTreeRec(List preOrder, List inOrder){ TreeNode root = null; List leftPreOrder; List rightPreOrder; List leftInorder; List rightInorder; int inorderPos; int preorderPos; if ((preOrder.size() != 0) && (inOrder.size() != 0)) { // 把preorder的第一个元素作为root root = new TreeNode(preOrder.get(0)); // Based upon the current node data seperate the traversals into leftPreorder, rightPreorder, // leftInorder, rightInorder lists // 因为知道root节点了,所以根据root节点位置,把preorder,inorder分别划分为 root左侧 和 右侧 的两个子区间 inorderPos = inOrder.indexOf(preOrder.get(0)); // inorder序列的分割点 leftInorder = inOrder.subList(0, inorderPos); rightInorder = inOrder.subList(inorderPos + 1, inOrder.size()); preorderPos = leftInorder.size(); // preorder序列的分割点 leftPreOrder = preOrder.subList(1, preorderPos + 1); rightPreOrder = preOrder.subList(preorderPos + 1, preOrder.size()); root.left = rebuildBinaryTreeRec(leftPreOrder, leftInorder); // root的左子树就是preorder和inorder的左侧区间而形成的树 root.right = rebuildBinaryTreeRec(rightPreOrder, rightInorder); // root的右子树就是preorder和inorder的右侧区间而形成的树 } return root; } /** 14. 判断二叉树是不是完全二叉树(迭代) 若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数, 第 h 层所有的结点都连续集中在最左边,这就是完全二叉树。 有如下算法,按层次(从上到下,从左到右)遍历二叉树,当遇到一个节点的左子树为空时, 则该节点右子树必须为空,且后面遍历的节点左右子树都必须为空,否则不是完全二叉树。 */ public static boolean isCompleteBinaryTree(TreeNode root){ if(root == null){ return false; } Queue queue = new LinkedList(); queue.add(root); boolean mustHaveNoChild = false; boolean result = true;
while( !queue.isEmpty() ){ TreeNode cur = queue.remove(); if(mustHaveNoChild){ // 已经出现了有空子树的节点了,后面出现的必须为叶节点(左右子树都为空) if(cur.left!=null || cur.right!=null){ result = false; break; } } else { if(cur.left!=null && cur.right!=null){ // 如果左子树和右子树都非空,则继续遍历 queue.add(cur.left); queue.add(cur.right); }else if(cur.left!=null && cur.right==null){ // 如果左子树非空但右子树为空,说明已经出现空节点,之后必须都为空子树 mustHaveNoChild = true; queue.add(cur.left); }else if(cur.left==null && cur.right!=null){ // 如果左子树为空但右子树非空,说明这棵树已经不是完全二叉完全树! result = false; break; }else{ // 如果左右子树都为空,则后面的必须也都为空子树 mustHaveNoChild = true; } } } return result; } /** * 14. 判断二叉树是不是完全二叉树(递归) * http://stackoverflow.com/questions/1442674/how-to-determine-whether-a-binary-tree-is-complete * */ public static boolean isCompleteBinaryTreeRec(TreeNode root){ // Pair notComplete = new Pair(-1, false); // return !isCompleteBinaryTreeSubRec(root).equalsTo(notComplete); return isCompleteBinaryTreeSubRec(root).height != -1; } // 递归判断是否满树(完美) public static boolean isPerfectBinaryTreeRec(TreeNode root){ return isCompleteBinaryTreeSubRec(root).isFull; } // 递归,要创建一个Pair class来保存树的高度和是否已满的信息 public static Pair isCompleteBinaryTreeSubRec(TreeNode root){ if(root == null){ return new Pair(0, true); } Pair left = isCompleteBinaryTreeSubRec(root.left); Pair right = isCompleteBinaryTreeSubRec(root.right); // 左树满节点,而且左右树相同高度,则是唯一可能形成满树(若右树也是满节点)的情况 if(left.isFull && left.height==right.height){ return new Pair(1+left.height, right.isFull); } // 左树非满,但右树是满节点,且左树高度比右树高