/*
* 判断两棵二叉树是否相同的树。
* 递归解法:
* (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);
}
/*
* 判断两棵二叉树是否相同的树。
* 迭代解法
* 我们直接用中序遍历来比较就好啦
* */
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<TreeNode> s1 = new Stack<TreeNode>();
Stack<TreeNode> s2 = new Stack<TreeNode>();
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;
}
/*.
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<TreeNode> q = new LinkedList<TreeNode>();
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;
}
/*
*
* 判断二叉树是不是平衡二叉树: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;
}
/*
* . 求二叉树中两个节点的最低公共祖先节点:
* */
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;
}
/*
* 求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;
}
/*
* 算法. 由前序遍历序列和中序遍历序列重建二叉树: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<Integer> preOrder, List<Integer> 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<Integer> preOrderLeft;
List<Integer> preOrderRight;
List<Integer> inOrderLeft;
List<Integer> 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;
}
/*
* * 求二叉树第K层的节点个数:getNodeNumKthLevelRec, getNodeNumKthLevel
* */
public static int getNodeNumKthLevel(TreeNode root, int k) {
if (root == null || k <= 0) {
return 0;
}
int level = 0;
Queue<TreeNode> q = new LinkedList<TreeNode>();
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;
}
/*
* * 求二叉树第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);
}
/*
* * 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;
}
}
/*
* .求叶子节点个数 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<TreeNode> s = new Stack<TreeNode>();
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;
}
转自:http://blog.youkuaiyun.com/yangcs2009/article/details/40146967
/**
* 求二叉树中两个节点的最低公共祖先节点
* 递归解法:
* (1)如果两个节点分别在根节点的左子树和右子树,则返回根节点
* (2)如果两个节点都在左子树,则递归处理左子树;如果两个节点都在右子树,则递归处理右子树
*/
public static TreeNode getLastCommonParentRec(TreeNode root, TreeNode n1, TreeNode n2) {
if (findNodeRec(root.left, n1)) { // 如果n1在树的左子树
if (findNodeRec(root.right, n2)) { // 如果n2在树的右子树
return root; // 返回根节点
} else { // 如果n2也在树的左子树
return getLastCommonParentRec(root.left, n1, n2); // 递归处理
}
} else { // 如果n1在树的右子树
if (findNodeRec(root.left, n2)) { // 如果n2在左子树
return root;
} else { // 如果n2在右子树
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;
}