方法一:递归法
思路:三种遍历方法最常用的就是递归法,写法非常对称,只需要调整当前层的添加顺序即可,于是,我们可以写出以下代码:
import java.util.*;
/* * public class TreeNode { * int val = 0; * TreeNode left = null; * TreeNode right = null; * } */
public class Solution {
/** * * @param root TreeNode类 the root of binary tree * @return int整型二维数组 */
ArrayList<Integer> preOrderList = new ArrayList<>();
ArrayList<Integer> midOrderList = new ArrayList<>();
ArrayList<Integer> proOrderList = new ArrayList<>();
public int[][] threeOrders (TreeNode root) {
// write code here
if (root == null) {
return new int[][]{
};
}
preOrder(root);
midOrder(root);
proOrder(root);
int len = preOrderList.size();
int[][] ret = new int[3][len];
// 前序遍历
for (int i = 0; i < len; i++) {
ret[0][i] = preOrderList.get(i);
}
// 中序遍历
for (int j = 0; j < len; j++) {
ret[1][j] = midOrderList.get(j);
}
// 后序遍历
for (int k = 0; k < len; k++) {
ret[2][k] = proOrderList.get(k);
}
return ret;
}
public void preOrder(TreeNode node) {
if (node == null) return;
preOrderList.add(node.val);
preOrder(node.left);
preOrder(node.right);
}
public void midOrder(TreeNode node) {
if (node == null) return;
midOrder(node.left);
midOrderList.add(node.val);
midOrder(node.right);
}
public void proOrder(TreeNode node) {
if (node == null) return;
proOrder(node.left);
proOrder(node.right);
proOrderList.add(node.val);
}
}
时间复杂度: O(n),其中 n 为二叉树节点的个数。二叉树的遍历中每个节点会被访问一次且只会被访问一次。
空间复杂度: O(n),空间复杂度取决于递归的栈深度,而栈深度在二叉树为一条链的情况下会达到 O(n) (最坏情况下)。
方法二:迭代法
思路:迭代法其实就是把方法一中的系统实现的递归栈变成自己手动实现一个递归栈,看下面的代码:
import java.util.*;
/* * public class TreeNode { * int val = 0; * TreeNode left = null; * TreeNode right = null; * } */
public class Solution {
/** * * @param root TreeNode类 the root of binary tree * @return int整型二维数组 */
static ArrayList<Integer> preOrderList = new ArrayList<>();
static ArrayList<Integer> midOrderList = new ArrayList<>();
static ArrayList<Integer> proOrderList = new ArrayList<>();
public int[][] threeOrders (TreeNode root) {
// write code here
if (root == null) {
return new int[][]{
};
}
preOrderForIteration(root);
midOrderForIteration(root);
proOrderForIteration(root);
int len = preOrderList.size();
int[][] ret = new int[3][len]; // 3 是前中后序遍历的数组个数
// 前序遍历
for (int i = 0; i < len; i++) {
ret[0][i] = preOrderList.get(i);
}
// 中序遍历
for (int i = 0; i < len; i++) {
ret[1][i] = midOrderList.get(i);
}
System.out.println();
// 后序遍历
for (int i = 0; i < len; i++) {
ret[2][i] = proOrderList.get(i);
}
return ret;
}
// 迭代写法
public static void preOrderForIteration(TreeNode root) {
// 前序遍历顺序:中-左-右,入栈顺序:中-右-左
if (root == null) return;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
preOrderList.add(node.val);
if (node.right != null) {
stack.push(node.right);
}
if (node.left != null) {
stack.push(node.left);
}
}
}
public static void midOrderForIteration(TreeNode root) {
// 中序遍历顺序:左-中-右,入栈顺序:左-右
if (root == null) return;
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()) {
if (cur != null) {
stack.push(cur);
cur = cur.left;
} else {
cur = stack.pop();
midOrderList.add(cur.val);
cur = cur.right;
}
}
}
public static void proOrderForIteration(TreeNode root) {
// 后序遍历顺序:左-右-中,入栈顺序:中-左-右 出栈顺序:中-右-左,最后翻转结果
if (root == null) return;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
proOrderList.add(node.val);
if (node.left != null) {
stack.push(node.left);
}
if (node.right != null) {
stack.push(node.right);
}
}
Collections.reverse(proOrderList);
}
}
时间复杂度: O(n),其中 n 为二叉树节点的个数。二叉树的遍历中每个节点会被访问一次且只会被访问一次。
空间复杂度: O(n),空间复杂度取决于递归的栈深度,而栈深度在二叉树为一条链的情况下会达到 O(n) (最坏情况下)。