二叉树是一种常见的基础数据结构,也是面试笔试中常常碰到的题目.
二叉树(英语:Binary tree)是每个节点最多只有两个分支(不存在分支度大于2的节点)的树结构。通常分支被称作“左子树”和“右子树”。二叉树的分支具有左右次序,不能颠倒。
二叉查找树,可实现对元素的快速查找,对二叉树的理解也是学习其他树结构的基础.
class BinaryTree{
int value;
BinaryTree left;
BinaryTree right;
public BinaryTree(int value){
this.value = value;
this.left = null;
this.right = null;
}
}
1. 树节点个数
2. 树的深度
3. 第K 层节点个数
4. 数的遍历:先序,中序,后序,层序
5. 树的镜像
6. 判断树中是否存在某元素
7. 是否是完全二叉树
8. 二叉树叶子节点个数
9. 判断两颗二叉树结构是否相同
10. 判断是否是平衡二叉树
11. 求二叉树中两个节点的最低公共祖先节点
12. 求二叉树中节点的最大距离
13. 由前序和中序遍历序列重建二叉树
1.1 思路
递归
1.2 代码
int getNumOfTree(BinaryTree root) {
if (root == null) {
return 0;
}
return 1+getNumOfTree(root.left)+getNumOfTree(root.right);
}
1.1 思路
递归
1.2 代码
int getDephthOfTree(BinaryTree root) {
if (root == null) {
return 0;
}
int leftHeight = getDephthOfTree(root.left);
int rightHeight = getDephthOfTree(root.right);
return leftHeight>rightHeight?leftHeight+1:rightHeight+1;
}
1.1 思路
递归
1.2 代码
private static int getNumberOfKth(BinaryTree root,int k) {
if (root == null || k<1) {
return 0;
}
if (k == 1) {
return 1;
}
int kthLeft = getNumberOfKth(root.left, k-1);
int kthRight = getNumberOfKth(root.right, k-1);
return kthLeft+kthRight;
}
1.1 思路
前序,中序,后序采用递归的方法,层序遍历借用队列来完成遍历.
1.2 代码
//前序
private static void preOrder(BinaryTree root) {
if (root != null) {
System.out.print(root.value+" ");
preOrder(root.left);
preOrder(root.right);
}
}
//中序
private static void inOrder(BinaryTree root) {
if (root != null) {
inOrder(root.left);
System.out.print(root.value+" ");
inOrder(root.right);
}
}
//后序
private static void postOrder(BinaryTree root) {
if (root != null) {
postOrder(root.left);
postOrder(root.right);
System.out.print(root.value+" ");
}
}
//层序
private static void leverOrder(BinaryTree root) {
if (root == null) {
return;
}
Queue queue = new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()){
BinaryTree pNode = queue.peek();
System.out.print(pNode.value+" ");
queue.remove();
if (pNode.left != null) {
queue.add(pNode.left);
}
if (pNode.right != null) {
queue.add(pNode.right);
}
}
}
1.1 思路
递归.
1.2 代码
private static BinaryTree mirror(BinaryTree root) {
if (root == null) {
return null;
}
BinaryTree left = mirror(root.left);
BinaryTree right = mirror(root.right);
root.left = right;
root.right = left;
return root;
}
1.1 思路
任选一遍历方法进行查找.
1.2 代码
private static void Find(BinaryTree root,int number) {
if (root != null) {
if (root.value == number) {
System.out.println("Found.");
return;
}
Find(root.left, number);
Find(root.right, number);
}
}
1.1 思路
使用队列进行遍历,若本层有未满子树,则下一层不应有节点.
1.2 代码
private static boolean isComplete(BinaryTree root) {
if (root == null) {
return true;
}
boolean hasNoChild = false; //本层有未满子树,则下一次不应该有节点.
boolean result = true;
Queue queue = new LinkedList<>();
queue.add(root);
while(!queue.isEmpty()){
BinaryTree pNode = queue.remove();
if (hasNoChild) {
if (pNode.left != null || pNode.right != null) {
result = false;
break;
}
}else {
if (pNode.left!= null && pNode.right != null) {
queue.add(pNode.left);
queue.add(pNode.right);
}else if (pNode.left == null && pNode.right != null) {
result = false;
break;
}else if(pNode.left != null && pNode.right == null){
hasNoChild = true; //进行下一轮扫描时,右子树为空
queue.add(pNode.left);
}else {
hasNoChild = true;
}
}
}
return result;
}
1.1 思路
递归.
1.2 代码
private static int getNumOfLeaf(BinaryTree root) {
if (root == null) {
return 0;
}
if (root.left == null && root.right == null) {
return 1;
}
int left = getNumOfLeaf(root.left);
int right = getNumOfLeaf(root.right);
return left+right;
}
1.1 思路
递归.
1.2 代码
private static boolean isCommon(BinaryTree root1, BinaryTree root2) {
if (root1 == null && root2 == null) {
return true;
}else if (root1 == null || root2 == null) {
return false;
}
boolean left = isCommon(root1.left, root2.left);
boolean right = isCommon(root1.right, root2.right);
return (left&&right);
}
1.1 思路
递归.
1.2 代码
private static boolean isAVL(BinaryTree root) {
if (root == null) {
return true;
}
int left_height = getDephthOfTree(root.left);
int right_height = getDephthOfTree(root.right);
int diff = left_height - right_height;
if (diff <-1 || diff > 1) {
return false;
}
return isAVL(root.left) && isAVL(root.right);
}
1.1 思路
从root开始遍历,如果n1和n2中的任一个和root匹配,那么root就是LCA。 如果都不匹配,则分别递归左、右子树,如果有一个 key(n1或n2)出现在左子树,并且另一个key(n1或n2)出现在右子树,则root就是LCA. 如果两个key都出现在左子树,则说明LCA在左子树中,否则在右子树。
1.2 代码
private static BinaryTree findLCA(BinaryTree root, BinaryTree pNode1, BinaryTree pNode2) {
if (root == null) {
return null;
}
if (root.value == pNode1.value || root.value == pNode2.value) {
return root;
}
BinaryTree left_lca = findLCA(root.left, pNode1, pNode2);
BinaryTree right_lca = findLCA(root.right, pNode1, pNode2);
if (left_lca != null && right_lca != null) {
return root;
}
return (left_lca !=null)?left_lca:right_lca;
}
1.1 思路
递归.
1.2 代码
//最大距离Max(左子树最大距离,右子树最大距离,左子树节点到根节点的最大距离+右子树节点到根节点的最大距离)
private static int height(BinaryTree root) {
if (root == null) {
return 0;
}
int heightLeft = height(root.left);
int heightRight = height(root.right);
return heightLeft>heightRight?(heightLeft+1):(heightRight+1);
}
private static int getMaxDistance(BinaryTree root) {
if (root == null) {
return 0;
}else if (root.left == null && root.right == null) {
return 0;
}
int dis = max(height(root.left)+height(root.right),getMaxDistance(root.left),getMaxDistance(root.right));
if (maxDis return dis;
}
private static int max(int a, int b, int c) {
int temp = a>b?a:b;
return temp>c?temp:c;
}
1.1 思路
递归.
1.2 代码
private static BinaryTree buildTree(int[] preOrder, int startPre, int endPre, int[] inOrder, int startIn, int endIn) {
if ((endPre-startPre) != (endIn-startIn)) {
return null;
}
if (preOrder == null || inOrder == null || preOrder.length<1 || inOrder.length <1) {
return null;
}
int rootValue = preOrder[startPre];
BinaryTree root = new BinaryTree(rootValue);
if ((startPre == endPre) && (startIn == endIn)) {
return root;
}
int rootIdx = startIn;
while (rootIdx <=endIn && inOrder[rootIdx]!=rootValue){
rootIdx ++;
}
if (rootIdx>endIn) {
return null;
}
int leftLength = rootIdx-startIn;
int leftPreorderLeft = leftLength + startPre;
if (leftLength>0) {
root.left = buildTree(preOrder, startPre+1, leftPreorderLeft, inOrder, startIn, rootIdx-1);
}
if (leftLength1, endPre, inOrder, rootIdx+1, endIn);
}
return root;
}