Traverse
Binary Tree Traversal: Preorder, Postorder, Inorder, Levelorder (Top-down, Bottom-up, Zigzag) Pre-order: root-left-right
Given a binary tree, return the preorder traversal of its nodes' values. For example: Given binary tree {1,#,2,3}, return [1,2,3]. 1 \ 2 / 3 Note: Recursive solution is trivial, could you do it iteratively?
Solution
Use a Stack: Time ~ O(N), Space ~ O(N) 先找到最左节点,然后一层层往上返回,没返回一层节点,要进入其右子树遍历(重复该过程)。
public class TreeNode {
int val;
TreeNode left, right;
TreeNode(int x) { val = x; }
}
// root-left-right
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
if (root == null) return list;
Stack<TreeNode> stack = new Stack<>();
TreeNode curr = root;
while (curr != null) {
list.add(curr.val);
stack.push(curr);
curr = curr.left;
}
while (!stack.isEmpty()) {
curr = stack.pop();
curr = curr.right;
while (curr != null) {
list.add(curr.val);
stack.push(curr);
curr = curr.left;
}
}
return list;
}
Post-order: left-right-root
Given a binary tree, return the postorder traversal of its nodes' values. For example: Given binary tree {1,#,2,3}, return [3,2,1]. Note: Recursive solution is trivial, could you do it iteratively?
Solution
Use a Stack: Time ~ O(N), Space ~ O(N) 先用mirrored preorder:root-right-left 然后再reverse整个结果:left-right-root
// left-right-root
public List<Integer> postorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
if (root == null) return list;
Stack<TreeNode> stackBack = new Stack<>(); // mirrored preorder
Stack<Integer> stack = new Stack<>(); // store mirrored preorder results
TreeNode curr = root;
while (curr != null) {
stack.push(curr.val);
stackBack.push(curr);
curr = curr.right;
}
while (!stackBack.isEmpty()) {
curr = stackBack.pop();
curr = curr.left;
while (curr != null) {
stack.push(curr.val);
stackBack.push(curr);
curr = curr.right;
}
}
// reverse: root-left-right (preoder) => right-left-root (postorder)
while (!stack.isEmpty()) {
list.add(stack.pop());
}
return list;
}
In-order : left-root-right
Given a binary tree, return the inorder traversal of its nodes' values. For example: Given binary tree {1,#,2,3}, return [1,3,2]. Note: Recursive solution is trivial, could you do it iteratively?
Solution
- Use a Stack: Time ~ O(N), Space ~ O(N) 先找最左节点,然后一层层往上返回,没返回一层节点,要进入其右子树遍历(重复该过程)。 注意:程序结构和pre-order几乎是一致的,仅是 list.add(curr.val) 的位置不同。
// left-root-right
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
if (root == null) return list;
Stack<TreeNode> stack = new Stack<>();
TreeNode curr = root;
while (curr != null) {
stack.push(curr);
curr = curr.left;
}
while (!stack.isEmpty()) {
curr = stack.pop();
list.add(curr.val);
curr = curr.right;
while (curr != null) {
stack.push(curr);
curr = curr.left;
}
}
return list;
}
- Morris Inorder Traversal: Time ~ O(N), Space ~ O(1) 改变Tree的结构,将node下最右节点连接node的parent,这样可以自动返回上层。 参见:wikipedia // Morris inorder traversal: Space ~ O(1)
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> list = new ArrayList<>();
TreeNode curr = root;
while (curr != null) {
if (curr.left != null) { // if curr has left children
TreeNode prev = curr.left;
while (prev.right != null && prev.right != curr) {
prev = prev.right; // find the rightmost node in curr's left subtree
}
if (prev.right == null) { // set right to successor, and go to left
prev.right = curr;
curr = curr.left;
} else { // visit and revert the change, and go to right
prev.right = null;
list.add(curr.val);
curr = curr.right;
}
} else { // if curr doesn't have left child, go to right
list.add(curr.val);
curr = curr.right;
}
}
return list;
}
Level-order: Top-Down
Given a binary tree, return the level order traversal of its nodes' values. (ie, from left to right, level by level). For example: Given binary tree {3,9,20,#,#,15,7}, return its level order traversal as: [ [3], [9,20], [15,7] ] 3 / \ 9 20 / \ 15 7
Solution
BFS: Time ~ O(N), Space ~ O(N) 用一个Queue,在遍历每一个节点的时候,将val加入List,并将其左右节点加入Queue中。 区分level:在每层结束后queue.add(null),接下来当 curr == null,表明到达该level的尾部。
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> listSet = new ArrayList<List<Integer>>();
if (root == null) return listSet;
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
queue.add(null); // flag of end-of-level
while (!queue.isEmpty()) {
List<Integer> list = new ArrayList<Integer>();
TreeNode curr = queue.poll();
while (curr != null) {
list.add(curr.val);
if (curr.left != null) queue.add(curr.left);
if (curr.right != null) queue.add(curr.right);
curr = queue.poll();
}
listSet.add(list);
if (!queue.isEmpty()) queue.add(null);
}
return listSet;
}
Level-order: Bottom-Up
Given a binary tree, return the bottom-up level order traversal of its nodes' values. (ie, from left to right, level by level from leaf to root). For example: Given binary tree {3,9,20,#,#,15,7}, return its bottom-up level order traversal as: [ [15,7], [9,20], [3] ]
Solution
BFS: Time ~ O(N), Space ~ O(N) 先用Top-down level-order,再将结果反转。
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> listSet = new ArrayList<List<Integer>>();
if (root == null) return listSet;
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
queue.add(null);
// top-down levelorder traversal
while (!queue.isEmpty()) {
List<Integer> list = new ArrayList<>();
TreeNode curr = queue.poll();
while (curr != null) {
list.add(curr.val);
if (curr.left != null) queue.add(curr.left);
if (curr.right != null) queue.add(curr.right);
curr = queue.poll();
}
listSet.add(list);
if (!queue.isEmpty()) queue.add(null);
}
// reverse the top-down levelorder traversal
Collections.reverse(listSet);
return listSet;
}
Level-order: Zigzag
Given a binary tree, return the zigzag level order traversal of its nodes' values. (ie, from left to right, then right to left for the next level and alternate between). For example: Given binary tree {3,9,20,#,#,15,7}, return its zigzag level order traversal as: [ [3], [20,9], [15,7] ]
Solution
BFS: Time ~ O(N), Space ~ O(N) 用两个Stack,stack存放当前行的node,stackTmp存放下一行的node。 另用一个boolean值记录奇偶行,由此决定放入左右node的顺序: 当oddLevel = true,先右后左; 当oddLevel = false,先左后右。
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> listSet = new ArrayList<List<Integer>>();
if (root == null) return listSet;
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
boolean oddLevel = false; // false - 0,2,4,...,levels
while (!stack.isEmpty()) {
List<Integer> list = new ArrayList<>();
Stack<TreeNode> stackTmp = new Stack<>();
while (!stack.isEmpty()) {
TreeNode curr = stack.pop();
list.add(curr.val);
if (oddLevel) {
if (curr.right != null) stackTmp.push(curr.right);
if (curr.left != null) stackTmp.push(curr.left);
} else {
if (curr.left != null) stackTmp.push(curr.left);
if (curr.right != null) stackTmp.push(curr.right);
}
}
listSet.add(list);
stack = stackTmp;
oddLevel = !oddLevel;
}
return listSet;
}