更多见手撕代码全集
面试手撕代码全集(树)
- 7. 二叉树
-
- 7.1 二叉树深度(递归)
- 7.2 二叉树节点总数、第K层节点数(递归)
- 7.3 前序、中序、后序遍历
- 7.4 层序遍历、分层换行、左视图、右视图
- 7.5 两个二叉树是否相同(结构、结构+数值) / 二叉树是否对称(两问题类似)
- 7.6 找到树中两个节点的最近的一个公共祖先
- 7.7 树中任意两个节点的最短路径
- 7.8 二叉搜索树中第K大的节点 / 第K小的节点
- 7.9 二叉树镜像反转
- 7.10 以1-N为节点的二叉搜索树的种类数 和 所有组成
- 7.11 重建二叉树 前序+中序,构建二叉树
- 7.12 判断B是否是A的子结构
- 7.13 判断一组序列是否是二叉搜索树的后序遍历结果
- 7.14 找到二叉树中一条和为某一值的路径(根节点到叶子节点)
- 7.15 二叉搜索树转换为排序的双向链表
- 7.16 二叉树中,查找给定节点按中序遍历的下一个节点
- 7.17 序列化和反序列化二叉树
- 二叉搜索树转为排序的双向链表
7. 二叉树
定义二叉树,二叉树的计算大部分都用递归方法实现,包括深度、前序、中序、后序等
//定义二叉树节点
public static class TreeNode {
int value; //数据域 可为其他类型
TreeNode leftNode; //左节点
TreeNode rightNode; //右节点
public TreeNode(int value, TreeNode leftNode, TreeNode rightNode) {
this.value = value;
this.leftNode = leftNode;
this.rightNode = rightNode;
}
public TreeNode(int value) {
this.value = value;
this.leftNode = null;
this.rightNode = null;
}
// value、leftNode、rightNode节点的Getter、Setter被省略
}
//定义二叉树类
public static class BinaryTree {
TreeNode root;
public BinaryTree(TreeNode root) {
this.root = root;
}
}
7.1 二叉树深度(递归)
public int getDeep(TreeNode root) {
int deep = 0;
if (root != null) {
int leftDeep = getDeep(root.leftNode);
int rightDeep = getDeep(root.rightNode);
deep = leftDeep > rightDeep ? 1 + leftDeep : 1 + rightDeep;
//or
// deep = 1+Math.max(getDeep(root.leftNode),getDeep(root.rightNode));
}
return deep;
}
7.2 二叉树节点总数、第K层节点数(递归)
//计算树节点总数
public int getNodeNum(TreeNode root) {
int num = 0;
if (root != null) {
num = getNodeNum(root.leftNode) + getNodeNum(root.rightNode) + 1;
}
return num;
}
//第K层 节点数 递归
public int getKNum(TreeNode root, int k) {
if (root == null)
return 0;
if (k == 0) {
return 1;
} else {
int leftNum = getKNum(root.leftNode, k - 1);
int rightNum = getKNum(root.rightNode, k - 1);
return (leftNum + rightNum);
}
}
//第K层 节点数 非递归
public int getkNum(TreeNode root, int k) {
if(root == null)
return 0;
if( k == 0)
return 1;
LinkedList<TreeNode> queue = new LinkedList<>();
queue.offer(root);
TreeNode node = null;
int size = 0, i = 0;
while(!queue.isEmpty() && i<=k) {
size = queue.size();
for (int j = 0; j < size; j++) {
node = queue.poll();
if (node.leftNode != null)
queue.offer(node.leftNode);
if (node.rightNode != null)
queue.offer(node.rightNode);
}
i++;
}
return size;
}
7.3 前序、中序、后序遍历
//递归 前序、中序、后序遍历 取决于不同位置取值
public void preOrder(TreeNode root) {
if (root != null) {
//位置1(前序遍历)System.out.print(root.value + " ");
preOrder(root.leftNode);
//位置2 (中序遍历) System.out.print(root.value + " ");
preOrder(root.rightNode);
//位置3 (后序遍历) System.out.print(root.value + " ");
}
}
//非递归 前序(位置1取值)、 中序(位置2取值)遍历
public void NPreOrder(TreeNode root) {
if (root == null)
return;
Stack<TreeNode> stack = new Stack<>();
TreeNode node = root;
while (!stack.isEmpty() || node != null) {
if (node != null) {
//位置1(前序遍历) System.out.print(node.value + " ");
stack.push(node);
node = node.leftNode;
} else {
node = stack.pop();
//位置2(中序遍历) System.out.print(node.value + " ");
node = node.rightNode;
}
}
}
//非递归 后序遍历
public void NPostOrder(TreeNode root) {
if(root