從大的層面講染突,Binary Tree 可以用DFS和BFS兼雄。
- 對于BFS梧税,我們需要 iterative with queue。
- 對于DFS侵蒙,Binary Tree 有三種traversal的方式:
** Inorder Traversal: left -> root -> right
** Preoder Traversal: root -> left -> right
** Postoder Traveral: left -> right -> root
記憶方式:order的名字指的是root在什么位置造虎。left,right的相對位置是固定的蘑志。
圖片來源:https://leetcode.com/articles/binary-tree-right-side-view/
對于時間復(fù)雜度來說累奈,基本上都是O(n)贬派,因為要訪問所有的點。
對于空間復(fù)雜度來說澎媒,BFS取決于掃描過程中每層的node數(shù)搞乏,就是樹的寬度,而DFS取決于掃描過程中樹的深度戒努。最壞情況兩個都是O(n)请敦。
本文重點討論iterative和recursive方法。對于morris储玫,另開一篇介紹侍筛。
Inorder Traversal
首先是recursion寫法,相對簡單:
// left->root->right
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) {
return res;
}
res.addAll(inorderTraversal(root.left));
res.add(root.val);
res.addAll(inorderTraversal(root.left));
}
如果用iteration:
public List<Integer> inorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) {
return res;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (cur != null || !stack.isEmpty()) {
while (cur != null) { // 把左路徑上遇到的點都放進stack里面
stack.push(cur);
cur = cur.left;
} // while循環(huán)結(jié)束的時候撒穷,cur==null
cur = stack.pop();
res.add(cur.val);
cur = cur.right;
}
return res;
}
Preorder Traversal
首先是recursion寫法匣椰,相對簡單:
// root->left->right
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) {
return res;
}
res.add(root.val);
res.addAll(inorderTraversal(root.left));
res.addAll(inorderTraversal(root.left));
}
如果用iteration:
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) {
return res;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
TreeNode cur = root;
while (!stack.isEmpty()) {
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;
}
Postorder Traversal
首先是recursion寫法,相對簡單:
// left->right->root
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) {
return res;
}
res.addAll(inorderTraversal(root.left));
res.addAll(inorderTraversal(root.left));
res.add(root.val);
}
如果用iteration:
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new LinkedList<>(); // 便于Insert操作
if (root == null) {
return res;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode node = stack.pop();
res.add(0, node.val); // 因為這一步端礼,所以轉(zhuǎn)變成了root->right->left
if (node.left != null) {
stack.push(node.left);
}
if (node.right != null) {
stack.push(node.right);
}
}
return res;
}