一、前中后序递归
1. 前序递归( 时间复杂度O(n)、空间复杂度O(n) )
class Solution { public List<Integer> preorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<>(); dfs(root, res); return res; } private void dfs(TreeNode root, List<Integer> res) { if (root == null) return; res.add(root.val); // 根 dfs(root.left, res); // 左 dfs(root.right, res); // 右 } }
2. 中序递归( 时间复杂度O(n)、空间复杂度O(n) )
class Solution { public List<Integer> inorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<>(); dfs(root,res); return res; } private void dfs(TreeNode root, List<Integer> res) { if (root == null) return; dfs(root.left, res); // 左 res.add(root.val); // 根 dfs(root.right, res); // 右 } }
3. 后序递归( 时间复杂度O(n)、空间复杂度O(n) )
class Solution { public List<Integer> postorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<>(); dfs(root, res); return res; } private void dfs(TreeNode root, List<Integer> res) { if (root == null) return; dfs(root.left, res); // 左 dfs(root.right, res);// 右 res.add(root.val);// 根 } }
二、前中后序非递归
前中后序遍历都属于深度遍历,所以需要使用栈。层次遍历需要用到队列。
1. 前序非递归( 时间复杂度O(n)、空间复杂度O(n) )
class Solution { public List<Integer> preorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<>(); Stack<TreeNode> stack = new Stack<>(); while (!stack.isEmpty() || root != null) { while (root != null) { res.add(root.val); stack.push(root); root = root.left; } root = stack.pop(); root = root.right; } return res; } }
非递归前序遍历的另一种写法:
class Solution { public List<Integer> preorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<>(); if (root == null) return res; Stack<TreeNode> stack = new Stack<>(); stack.push(root); while (!stack.isEmpty()) { TreeNode cur = stack.pop(); res.add(cur.val); if (cur.right != null) stack.push(cur.right); // 先加入右子树 if (cur.left != null) stack.push(cur.left); } return res; } }
2. 中序非递归( 时间复杂度O(n)、空间复杂度O(n) )
class Solution { public List<Integer> inorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<>(); Stack<TreeNode> stack = new Stack<>(); while (!stack.isEmpty() || root != null) { while (root != null) { stack.push(root); root = root.left; } root = stack.pop(); res.add(root.val); root = root.right; } return res; } }
3.后序非递归( 时间复杂度O(n)、空间复杂度O(n) )
class Solution { public List<Integer> postorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<>(); Stack<TreeNode> stack = new Stack<>(); TreeNode pre = null; //pre节点用于记录前一次访问的节点 while (!stack.isEmpty() || root != null) { while (root != null) { stack.push(root); root = root.left; } root = stack.peek(); // 若右节点为空 或右节点访问过 if (root.right == null || root.right == pre) { res.add(root.val); //此时可以访问根结点啦 stack.pop(); pre = root; root = null; //此时下一轮循环不要将左子树压栈,直接判断栈顶元素 }else { root = root.right; //先不出栈 把它右节点入栈 } } return res; } }
后序非递归的另一种写法,修改前序【根左右】的遍历顺序为【根右左】,前序遍历是往后加元素,后序遍历是往前加元素
class Solution { //修改前序遍历,每次先查看右节点再查看左节点。同时,节点写入结果将插入队尾修改为插入队首 public List<Integer> postorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<>(); Stack<TreeNode> stack = new Stack<>(); while (!stack.isEmpty() || root != null) { while (root != null) { res.add(0,root.val); // 取根节点的值,插入list最后边 stack.push(root); root = root.right; // 遍历右子树 } root = stack.pop(); root = root.left; // 遍历左子树 } return res; } }
三、层序遍历
class Solution { public List<List<Integer>> levelOrder(TreeNode root) { List<List<Integer>> res = new ArrayList<>(); if (root == null) return res; Queue<TreeNode> queue = new LinkedList<>(); // 层序需要借助队列 queue.offer(root); while (!queue.isEmpty()) { int level = queue.size(); List<Integer> list = new ArrayList<>(); for (int i = 0; i < level; i++) { TreeNode cur = queue.poll(); list.add(cur.val); if (cur.left != null) queue.offer(cur.left); if (cur.right != null) queue.offer(cur.right); } res.add(list); } return res; } }
四、相关习题
LeetCode144. 二叉树的前序遍历、LeetCode94. 二叉树的中序遍历、LeetCode145. 二叉树的后序遍历、LeetCode102. 二叉树的层序遍历
参考: