今天是记录leetcode刷题的第二天,今天的题作为回忆二叉树的相关知识。
今日题目来源:
其实,二叉树结构还是比较简答的结构,因为用来用去就是那么两个子节点。
先来说一下二叉树的前序、中序、后序吧。
- 前序:从根节点出发,先深度优先遍历左子树,在深度优先遍历右子树
- 中序:先深度优先遍历左子树,再回到根节点,然后在深度优先遍历右子树
- 后序:先深度优先遍历左子树,在深度优先遍历右子树,最后回到根节点。
可以看到,不论前序、中序还是后序,左右的优先级是不会改变的,都是先左后右,改变的只有根节点的相对位置,所以可以按照以下结论来遍历
- 前序:{根节点,左子树,右子树}
- 中序:{左子树,根节点,右子树}
- 后序:{左子树,右子树,根节点}
在使用代码实现时,树形结构的遍历一般都会使用递归来实现,因为单一的循环是不足以支持两个变量同时循环的,而树有两个节点同时循环。
剩下的就是根据题意将节点值输出或入栈。
代码如下:
public int[][] threeOrders(TreeNode root) {
if(root == null){
return new int[3][0];
}
Stack<TreeNode> stack = new Stack<>();
// 先序栈
eqPreStack(stack, root);
int size = stack.size();
// 有size之后,声明
int[][] treeOrder = new int[3][size];
// 遍历,放到int[]
int index = size;
while (!stack.isEmpty()){
TreeNode pop = stack.pop();
treeOrder[0][--index] = pop.val;
}
// 中序栈
eqMidStack(stack, root);
// 清空栈
index = size;
while (!stack.isEmpty()){
TreeNode pop = stack.pop();
treeOrder[1][--index] = pop.val;
}
eqEndStack(stack, root);
// 清空栈
index = size;
while (!stack.isEmpty()){
TreeNode pop = stack.pop();
treeOrder[2][--index] = pop.val;
}
return treeOrder;
}
private void eqPreStack(Stack<TreeNode> stack, TreeNode node) {
stack.add(node);
if (node.left != null) {
eqPreStack(stack, node.left);
}
if (node.right != null) {
eqPreStack(stack, node.right);
}
}
private void eqMidStack(Stack<TreeNode> stack, TreeNode node) {
if (node.left != null) {
eqMidStack(stack, node.left);
}
stack.add(node);
if (node.right != null) {
eqMidStack(stack, node.right);
}
}
private void eqEndStack(Stack<TreeNode> stack, TreeNode node) {
if (node.left != null) {
eqEndStack(stack, node.left);
}
if (node.right != null) {
eqEndStack(stack, node.right);
}
stack.add(node);
}
public static class TreeNode {
int val = 0;
public TreeNode(int val) {
this.val = val;
}
TreeNode left = null;
TreeNode right = null;
}
测试案例:
// 需要自备测试依赖,或将测试方法改为main方法
@Test
public void test(){
TreeNode node = new TreeNode(1);
node.left = new TreeNode(2);
node.right = new TreeNode(3);
threeOrders(node);
}
附newcode截图