package 树;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.Stack;
/**
* http://blog.youkuaiyun.com/luckyxiaoqiang/article/details/7518888 轻松搞定面试中的二叉树题目
* http://www.cnblogs.com/Jax/archive/2009/12/28/1633691.html 算法大全(3) 二叉树
*
* TODO: 一定要能熟练地写出所有问题的递归和非递归做法!
*
* 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 10.1 判断两个树是否互相镜像:isMirrorRec 11.
* 求二叉树中两个节点的最低公共祖先节点:getLastCommonParent, getLastCommonParentRec,
* getLastCommonParentRec2 12. 求二叉树中节点的最大距离:getMaxDistanceRec 13.
* 由前序遍历序列和中序遍历序列重建二叉树:rebuildBinaryTreeRec
* 14.判断二叉树是不是完全二叉树:isCompleteBinaryTree, isCompleteBinaryTreeRec
*
*/
public class Demo {
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);
r1.left = r2;
r1.right = r3;
r2.left = r4;
r2.right = r5;
r3.right = r6;
System.out.println(getDepth(r1));
}
private static class TreeNode {
int val;
TreeNode left;
TreeNode right;
public TreeNode(int val) {
this.val = val;
}
}
/**
* 求二叉树中的节点个数递归解法: O(n) (1)如果二叉树为空,节点个数为0 (2)如果二叉树不为空,二叉树节点个数 = 左子树节点个数 +
* 右子树节点个数 + 1
*/
public static int getNodeNumRec(TreeNode root) {
if (root == null) {
return 0;
} else {
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;
}
int count = 1;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode cur = queue.remove();
if (cur.left != null) {
queue.add(cur.left);
count++;
}
if (cur.right != null) {
queue.add(cur.right);
count++;
}
}
return count;
}
/**
* 求二叉树的深度(高度) 递归解法: O(n) (1)如果二叉树为空,二叉树的深度为0 (2)如果二叉树不为空,二叉树的深度 =
* max(左子树深度, 右子树深度) + 1
*/
public static int getDepthRec(TreeNode root) {
if (root == null) {
return 0;
}
int leftDepth = getDepthRec(root.left);
int rightDepth = getDepthRec(root.right);
return Math.max(leftDepth, rightDepth) + 1;
}
/**
* 求二叉树的深度(高度) 迭代解法: O(n) 基本思想同LevelOrderTraversal,还是用一个Queue
*/
public static int getDepth(TreeNode root) {
if (root == null) {
return 0;
}
int depth = 0;
int currentLevelNodes = 1;
int nextLevelNodes = 0;
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode cur = queue.remove();
currentLevelNodes--;
if (cur.left != null) {
queue.add(cur.left);
nextLevelNodes++;
}
if (cur.right != null) {
queue.add(cur.right);
nextLevelNodes++;
}
if (currentLevelNodes == 0) {
depth++;
currentLevelNodes = nextLevelNodes;
nextLevelNodes = 0;
}
}
return depth;
}
/**
* 前序遍历,中序遍历,后序遍历 前序遍历递归解法: (1)如果二叉树为空,空操作 (2)如果二叉树不为空,访问根节点,前序遍历左子树,前序遍历右子树
*/
public static void preorderTraversalRec(TreeNode root) {
if (root == null) {
return;
}
System.out.print(root.val + " ");
preorderTraversalRec(root.left);
preorderTraversalRec(root.right);
}
/**
* 前序遍历迭代解法:用一个辅助stack,总是把右孩子放进栈 http://www.youtube.com/watch?v=uPTCbdHSFg4
*/
public static void preorderTraversal(TreeNode root) {
if (root == null) {
return;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode cur = stack.pop();
System.out.print(cur.val + " ");
if (cur.right != null) {
stack.push(cur.right);
}
if (cur.left != null) {
stack.push(cur.left);
}
}
}
/**
* 中序遍历递归解法 (1)如果二叉树为空,空操作。 (2)如果二叉树不为空,中序遍历左子树,访问根节点,中序遍历右子树
*/
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<TreeNode> stack = new Stack<TreeNode>();
TreeNode cur = root;
while (true) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
if (stack.isEmpty()) {
break;
}
cur = stack.pop();
System.out.print(cur.val + " ");
cur = cur.right;
}
}
/**
* 后序遍历递归解法 (1)如果二叉树为空,空操作 (2)如果二叉树不为空,后序遍历左子树,后序遍历右子树,访问根节点
*/
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
*
*/
public static void postorderTraversal(TreeNode root) {
if (root == null) {
return;
}
Stack<TreeNode> s = new Stack<TreeNode>();
Stack<TreeNode> output = new Stack<TreeNode>();
s.push(root);
while (!s.isEmpty()) {
TreeNode cur = s.pop();
output.push(cur);
if (cur.left != null) {
s.push(cur.left);
}
if (cur.right != null) {
s.push(cur.right);
}
}
while (!output.isEmpty()) {
System.out.print(output.pop().val + " ");
}
}
/**
* 分层遍历二叉树(按层次从上往下,从左往右)迭代
* 相当于广度优先搜索,使用队列实现。队列初始化,将根节点压入队列。当队列不为空,进行如下操作:弹出一个节点
* ,访问,若左子节点或右子节点不为空,将其压入队列
*/
public static void levelTraversal(TreeNode root) {
if (root == null) {
return;
}
LinkedList<TreeNode> queue = new LinkedList<TreeNode>();
queue.push(root);
while (!queue.isEmpty()) {
TreeNode cur = queue.removeFirst();
System.out.print(cur.val + " ");
if (cur.left != null) {
queue.add(cur.left);
}
if (cur.right != null) {
queue.add(cur.right);
}
}
}
/**
* 分层遍历二叉树(递归) 很少有人会用递归去做level traversal
* 基本思想是用一个大的ArrayList,里面包含了每一层的ArrayList。 大的ArrayList的size和level有关系
*
* 这是我目前见到的最好的递归解法!
* http://discuss.leetcode.com/questions/49/binary-tree-level
* -order-traversal#answer-container-2543
*/
public static void levelTraversalRec(TreeNode root) {
ArrayList<ArrayList<Integer>> ret = new ArrayList<ArrayList<Integer>>();
dfs(root, 0, ret);
System.out.println(ret);
}
private static void dfs(TreeNode root, int level, ArrayList<ArrayList<Integer>> ret) {
if (root == null) {
return;
}
if (level >= ret.size()) {
ret.add(new ArrayList<Integer>());
}
ret.get(level).add(root.val);
dfs(root.left, level + 1, ret);
dfs(root.right, level + 1, ret);
}
/**
* 将二叉查找树变为有序的双向链表 要求不能创建新节点,只调整指针。 递归解法:
* 参考了http://stackoverflow.com/questions
* /11511898/converting-a-binary-search-
* tree-to-doubly-linked-list#answer-11530016
* 感觉是最清晰的递归解法,但要注意递归完,root会在链表的中间位置,因此要手动 把root移到链表头或链表尾
*/
public static TreeNode convertBST2DLLRec(TreeNode root) {
root = convertBST2DLLSubRec(root);
while (root.left != null) {
root = root.left;
}
return root;
}
/**
* 递归转换BST为双向链表(DLL)
*/
public static TreeNode convertBST2DLLSubRec(TreeNode root) {
if (root == null || (root.left == null && root.right == null)) {
return root;
}
TreeNode tmp = null;
if (root.left != null) {
tmp = convertBST2DLLSubRec(root.left);
while (tmp.right != null) {
tmp = tmp.right;
}
tmp.right = root;
root.left = tmp;
}
if (root.right != null) {
tmp = convertBST2DLLSubRec(root.right);
while (tmp.left != null) {
tmp = tmp.left;
}
tmp.left = root;
root.right = tmp;
}
return root;
}
/**
* 将二叉查找树变为有序的双向链表 迭代解法 // * 类似inorder traversal的做法
*/
public static TreeNode convertBST2DLL(TreeNode root) {
if (root == null) {
return null;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode cur = root;
TreeNode old = null;
TreeNode head = null;
while (true) {
while (cur != null) {
stack.push(cur);
cur = cur.left;
}
if (stack.isEmpty()) {
break;
}
cur = stack.pop();
if (old != null) {
old.right = cur;
}
if (head == null) {
head = cur;
}
old = cur;
cur = cur.right;
}
return head;
}
/**
* 求二叉树第K层的节点个数 递归解法: (1)如果二叉树为空或者k<1返回0 (2)如果二叉树不为空并且k==1,返回1
* (3)如果二叉树不为空且k>1,返回root左子树中k-1层的节点个数与root右子树k-1层节点个数之和
*
* 求以root为根的k层节点数目 等价于 求以root左孩子为根的k-1层(因为少了root那一层)节点数目 加上
* 以root右孩子为根的k-1层(因为少了root那一层)节点数目
*
* 所以遇到树,先把它拆成左子树和右子树,把问题降解
*
*/
public static int getNodeNumKthLevelRec(TreeNode root, int k) {
if (root == null || k < 1) {
return 0;
}
if (k == 1) {
return 1;
}
int numLeft = getNodeNumKthLevelRec(root.left, k - 1);
int numRight = getNodeNumKthLevelRec(root.right, k - 1);
return numLeft + numRight;
}
/**
* 求二叉树第K层的节点个数 迭代解法: 同getDepth的迭代解法
*/
public static int getNodeNumKthLevel(TreeNode root, int k) {
if (root == null) {
return 0;
}
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
int i = 1;
int currentLevelNodes = 1;
int nextLevelNodes = 0;
while (!queue.isEmpty() && i < k) {
TreeNode cur = queue.remove();
currentLevelNodes--;
if (cur.left != null) {
queue.add(cur.left);
nextLevelNodes++;
}
if (cur.right != null) {
queue.add(cur.right);
nextLevelNodes++;
}
if (currentLevelNodes == 0) {
currentLevelNodes = nextLevelNodes;
nextLevelNodes = 0;
i++;
}
}
return currentLevelNodes;
}
/**
* 求二叉树中叶子节点的个数(递归)
*/
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);
}
/**
* 求二叉树中叶子节点的个数(迭代) 还是基于Level order traversal
*/
public static int getNodeNumLeaf(TreeNode root) {
if (root == null) {
return 0;
}
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
int leafNodes = 0;
while (!queue.isEmpty()) {
TreeNode cur = queue.remove();
if (cur.left != null) {
queue.add(cur.left);
}
if (cur.right != null) {
queue.add(cur.right);
}
if (cur.left == null && cur.right == null) {
leafNodes++;
}
}
return leafNodes;
}
/**
* 判断两棵二叉树是否相同的树。 递归解法: (1)如果两棵二叉树都为空,返回真 (2)如果两棵二叉树一棵为空,另一棵不为空,返回假
* (3)如果两棵二叉树都不为空,如果对应的左子树和右子树都同构返回真,其他返回假
*/
public static boolean isSameRec(TreeNode r1, TreeNode r2) {
if (r1 == null && r2 == null) {
return true;
}
else if (r1 == null || r2 == null) {
return false;
}
if (r1.val != r2.val) {
return false;
}
boolean leftRes = isSameRec(r1.left, r2.left);
boolean rightRes = isSameRec(r1.right, r2.right);
return leftRes && rightRes;
}
/**
* 判断两棵二叉树是否相同的树(迭代) 遍历一遍即可,这里用preorder
*/
public static boolean isSame(TreeNode r1, TreeNode r2) {
if (r1 == null && r2 == null) {
return true;
}
if (r1 == null || r2 == null) {
return false;
}
Stack<TreeNode> s1 = new Stack<TreeNode>();
Stack<TreeNode> s2 = new Stack<TreeNode>();
s1.push(r1);
s2.push(r2);
while (!s1.isEmpty() && !s2.isEmpty()) {
TreeNode n1 = s1.pop();
TreeNode n2 = s2.pop();
if (n1 == null && n2 == null) {
continue;
} else if (n1 != null && n2 != null && n1.val == n2.val) {
s1.push(n1.right);
s1.push(n1.left);
s2.push(n2.right);
s2.push(n2.left);
} else {
return false;
}
}
return true;
}
/**
* 判断二叉树是不是平衡二叉树 递归解法: (1)如果二叉树为空,返回真
* (2)如果二叉树不为空,如果左子树和右子树都是AVL树并且左子树和右子树高度相差不大于1,返回真,其他返回假
*/
public static boolean isAVLRec(TreeNode root) {
if (root == null) {
return true;
}
if (Math.abs(getDepthRec(root.left) - getDepthRec(root.right)) > 1) {
return false;
}
return isAVLRec(root.left) && isAVLRec(root.right);
}
/**
* 求二叉树的镜像 递归解法: (1)如果二叉树为空,返回空 (2)如果二叉树不为空,求左子树和右子树的镜像,然后交换左子树和右子树
*/
public static TreeNode mirrorRec(TreeNode root) {
if (root == null) {
return null;
}
TreeNode left = mirrorRec(root.left);
TreeNode right = mirrorRec(root.right);
root.left = right;
root.right = left;
return root;
}
public static TreeNode mirrorCopyRec(TreeNode root) {
if (root == null) {
return null;
}
TreeNode newNode = new TreeNode(root.val);
newNode.left = mirrorCopyRec(root.right);
newNode.right = mirrorCopyRec(root.left);
return newNode;
}
public static boolean isMirrorRec(TreeNode r1, TreeNode r2) {
if (r1 == null && r2 == null) {
return true;
}
else if (r1 == null || r2 == null) {
return false;
}
if (r1.val != r2.val) {
return false;
}
return isMirrorRec(r1.left, r2.right) && isMirrorRec(r1.right, r2.left);
}
public static void mirror(TreeNode root) {
if (root == null) {
return;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode cur = stack.pop();
TreeNode tmp = cur.right;
cur.right = cur.left;
cur.left = tmp;
if (cur.right != null) {
stack.push(cur.right);
}
if (cur.left != null) {
stack.push(cur.left);
}
}
}
public static TreeNode mirrorCopy(TreeNode root) {
if (root == null) {
return null;
}
Stack<TreeNode> stack = new Stack<TreeNode>();
Stack<TreeNode> newStack = new Stack<TreeNode>();
stack.push(root);
TreeNode newRoot = new TreeNode(root.val);
newStack.push(newRoot);
while (!stack.isEmpty()) {
TreeNode cur = stack.pop();
TreeNode newCur = newStack.pop();
if (cur.right != null) {
stack.push(cur.right);
newCur.left = new TreeNode(cur.right.val);
newStack.push(newCur.left);
}
if (cur.left != null) {
stack.push(cur.left);
newCur.right = new TreeNode(cur.left.val);
newStack.push(newCur.right);
}
}
return newRoot;
}
/**
* 求二叉树中两个节点的最低公共祖先节点 递归解法: (1)如果两个节点分别在根节点的左子树和右子树,则返回根节点
* (2)如果两个节点都在左子树,则递归处理左子树;如果两个节点都在右子树,则递归处理右子树
*/
public static TreeNode getLastCommonParentRec(TreeNode root, TreeNode n1, TreeNode n2) {
if (findNodeRec(root.left, n1)) {
if (findNodeRec(root.right, n2)) {
return root;
} else {
return getLastCommonParentRec(root.left, n1, n2);
}
} else {
if (findNodeRec(root.left, n2)) {
return root;
} else {
return getLastCommonParentRec(root.right, n1, n2);
}
}
}
private static boolean findNodeRec(TreeNode root, TreeNode node) {
if (root == null || node == null) {
return false;
}
if (root == node) {
return true;
}
boolean found = findNodeRec(root.left, node);
if (!found) {
found = findNodeRec(root.right, node);
}
return found;
}
public static TreeNode getLastCommonParentRec2(TreeNode root, TreeNode n1, TreeNode n2) {
if (root == null) {
return null;
}
if (root.equals(n1) || root.equals(n2)) {
return root;
}
TreeNode commonInLeft = getLastCommonParentRec2(root.left, n1, n2);
TreeNode commonInRight = getLastCommonParentRec2(root.right, n1, n2);
if (commonInLeft != null && commonInRight != null) {
return root;
}
if (commonInLeft != null) {
return commonInLeft;
}
return commonInRight;
}
/**
* 非递归解法: 先求从根节点到两个节点的路径,然后再比较对应路径的节点就行,最后一个相同的节点也就是他们在二叉树中的最低公共祖先节点
*/
public static TreeNode getLastCommonParent(TreeNode root, TreeNode n1, TreeNode n2) {
if (root == null || n1 == null || n2 == null) {
return null;
}
ArrayList<TreeNode> p1 = new ArrayList<TreeNode>();
boolean res1 = getNodePath(root, n1, p1);
ArrayList<TreeNode> p2 = new ArrayList<TreeNode>();
boolean res2 = getNodePath(root, n2, p2);
if (!res1 || !res2) {
return null;
}
TreeNode last = null;
Iterator<TreeNode> iter1 = p1.iterator();
Iterator<TreeNode> iter2 = p2.iterator();
while (iter1.hasNext() && iter2.hasNext()) {
TreeNode tmp1 = iter1.next();
TreeNode tmp2 = iter2.next();
if (tmp1 == tmp2) {
last = tmp1;
} else {
break;
}
}
return last;
}
private static boolean getNodePath(TreeNode root, TreeNode node, ArrayList<TreeNode> path) {
if (root == null) {
return false;
}
path.add(root);
if (root == node) {
return true;
}
boolean found = false;
found = getNodePath(root.left, node, path);
if (!found) {
found = getNodePath(root.right, node, path);
}
if (!found) {
path.remove(root);
}
return found;
}
/**
* 求二叉树中节点的最大距离 即二叉树中相距最远的两个节点之间的距离。 (distance / diameter) 递归解法:
* (1)如果二叉树为空,返回0,同时记录左子树和右子树的深度,都为0
* (2)如果二叉树不为空,最大距离要么是左子树中的最大距离,要么是右子树中的最大距离,
* 要么是左子树节点中到根节点的最大距离+右子树节点中到根节点的最大距离, 同时记录左子树和右子树节点中到根节点的最大距离。
*
* http://www.cnblogs.com/miloyip/archive/2010/02/25/1673114.html
*
* 计算一个二叉树的最大距离有两个情况:
*
* 情况A: 路径经过左子树的最深节点,通过根节点,再到右子树的最深节点。 情况B: 路径不穿过根节点,而是左子树或右子树的最大距离路径,取其大者。
* 只需要计算这两个情况的路径距离,并取其大者,就是该二叉树的最大距离
*/
public static Result getMaxDistanceRec(TreeNode root) {
if (root == null) {
Result empty = new Result(0, -1);
return empty;
}
Result lmd = getMaxDistanceRec(root.left);
Result rmd = getMaxDistanceRec(root.right);
Result res = new Result();
res.maxDepth = Math.max(lmd.maxDepth, rmd.maxDepth) + 1;
res.maxDistance = Math.max(lmd.maxDepth + rmd.maxDepth, Math.max(lmd.maxDistance, rmd.maxDistance));
return res;
}
private static class Result {
int maxDistance;
int maxDepth;
public Result() {
}
public Result(int maxDistance, int maxDepth) {
this.maxDistance = maxDistance;
this.maxDepth = maxDepth;
}
}
/**
* 13. 由前序遍历序列和中序遍历序列重建二叉树(递归) 感觉这篇是讲的最为清晰的:
* http://crackinterviewtoday.wordpress
* .com/2010/03/15/rebuild-a-binary-tree-
* from-inorder-and-preorder-traversals/ 文中还提到一种避免开额外空间的方法,等下次补上
*/
public static TreeNode rebuildBinaryTreeRec(List<Integer> preOrder, List<Integer> inOrder) {
TreeNode root = null;
List<Integer> leftPreOrder;
List<Integer> rightPreOrder;
List<Integer> leftInorder;
List<Integer> rightInorder;
int inorderPos;
int preorderPos;
if ((preOrder.size() != 0) && (inOrder.size() != 0)) {
root = new TreeNode(preOrder.get(0));
inorderPos = inOrder.indexOf(preOrder.get(0));
leftInorder = inOrder.subList(0, inorderPos);
rightInorder = inOrder.subList(inorderPos + 1, inOrder.size());
preorderPos = leftInorder.size();
leftPreOrder = preOrder.subList(1, preorderPos + 1);
rightPreOrder = preOrder.subList(preorderPos + 1, preOrder.size());
root.left = rebuildBinaryTreeRec(leftPreOrder, leftInorder);
root.right = rebuildBinaryTreeRec(rightPreOrder, rightInorder);
}
return root;
}
/**
* 14. 判断二叉树是不是完全二叉树(迭代) 若设二叉树的深度为h,除第 h 层外,其它各层 (1~h-1) 的结点数都达到最大个数, 第 h
* 层所有的结点都连续集中在最左边,这就是完全二叉树。 有如下算法,按层次(从上到下,从左到右)遍历二叉树,当遇到一个节点的左子树为空时,
* 则该节点右子树必须为空,且后面遍历的节点左右子树都必须为空,否则不是完全二叉树。
*/
public static boolean isCompleteBinaryTree(TreeNode root) {
if (root == null) {
return false;
}
Queue<TreeNode> queue = new LinkedList<TreeNode>();
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) {
return isCompleteBinaryTreeSubRec(root).height != -1;
}
public static boolean isPerfectBinaryTreeRec(TreeNode root) {
return isCompleteBinaryTreeSubRec(root).isFull;
}
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);
}
if (right.isFull && left.height == right.height + 1) {
return new Pair(1 + left.height, false);
}
return new Pair(-1, false);
}
private static class Pair {
int height;
boolean isFull;
public Pair(int height, boolean isFull) {
this.height = height;
this.isFull = isFull;
}
public boolean equalsTo(Pair obj) {
return this.height == obj.height && this.isFull == obj.isFull;
}
}
public ArrayList<Integer> PrintFromTopToBottom(TreeNode root) {
ArrayList<Integer> l = new ArrayList<Integer>();
if (root == null)
return l;
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.add(root);
while (!queue.isEmpty()) {
TreeNode n = queue.poll();
l.add(n.val);
if (n.left != null)
queue.add(n.left);
if (n.right != null)
queue.add(n.right);
}
return l;
}
}