https://leetcode.com/problems/binary-tree-level-order-traversal/
对于二叉树,方法都是BFS和DFS两种。
BFS,全称Breadth First Search,中文名为广度优先搜索。是一种以宽度方向搜索某种数据结构的一种方法,常用队列实现BFS算法。广度优先搜索并不是某一个固定的算法,它是一类符合上述所说的算法。BFS一般为按层级遍历,每一层级搜索完后再进入下一层级。
DFS,全称Depth First Search,中文名为深度优先搜索。是一种以深度方向搜索某种数据结构的方法,常用栈来辅助DFS算法。深度优先搜索大多要以递归实现,所以要考虑递归爆栈的可能性。DFS是一条路走到黑,每次都遍历到最深的节点,再依次出栈,递归遍历。
BFS的实现:
public List<List<Integer>> levelOrder(TreeNode root) {
// iteration 解决方法,采用队列每次存储每一层的节点,再依次遍历
List<List<Integer>> res = new ArrayList<>();
if (root == null) return res; // 当输入为[]时候,返回不是null而是 []
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
while(!q.isEmpty()) {
List<Integer> subRes = new ArrayList<>(); // 该层的结果
int num = q.size(); // 该层的节点数量(1 0r 2)
for(int i = 0; i < num; i++) {
TreeNode curr = q.poll();
subRes.add(curr.val);
if (curr.left != null) {
q.offer(curr.left);
} if (curr.right != null) { // 此时不能是else if
q.offer(curr.right);
}
}
res.add(subRes);
}
return res;
}
DFS实现:
public List<List<Integer>> levelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
dfs(root, 0, res); // 使用dfs深度优先遍历binary tree
return res;
}
public void dfs(TreeNode node, int level, List<List<Integer>> res) {
if (node == null) {
return;
}
List<Integer> curr;
if (level + 1 > res.size()) { // 如果当前level大于结果res的size,表示为该层第一个节点,需要new并且添加值
curr = new ArrayList<>();
curr.add(node.val);
res.add(curr);
} else { // 否则表示该层已经存在一个节点,需要访问添加值即可
res.get(level).add(node.val);
}
dfs(node.left, level + 1, res); // dfs遍历左子树(先遍历左子树保证了结果的顺序)
dfs(node.right, level + 1, res); // dfs遍历右子树
}
}
https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/
这题和上题相比,只有节点的次序不同,这样和上面的BFS的实现相比,设置一个isZigzag的标志位表示当前层次是否按照zigzag顺序输出,如果是isZigzag,则将节点插入到对于层级结果的第一位,这样相当于在zigzag的层级实现了按照从右向左的输出(代码中红色为不同的部分)。
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
if (root == null) return res; // 当输入为[]时候,返回不是null而是 []
Queue<TreeNode> q = new LinkedList<>();
q.offer(root);
boolean isZigzag = false; // 是否是zigzag,是的话就是从右向左遍历,否则就是左向右
while(!q.isEmpty()) {
List<Integer> subRes = new ArrayList<>(); // 该层的结果
int num = q.size(); // 该层的节点数量(1 0r 2)
for(int i = 0; i < num; i++) {
TreeNode curr = q.poll();
if(isZigzag) { // 是zigzag,则插入到前面
subRes.add(0, curr.val);
} else {
subRes.add(curr.val);
}
if (curr.left != null ) q.offer(curr.left);
if (curr.right != null) q.offer(curr.right);
}
isZigzag = !isZigzag;
res.add(subRes);
}
return res;
}
DFS的解决方法和上面的BFS思想相同,只需要修改一点代码即可实现(代码中红色为不同的部分):
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> res = new ArrayList<>();
dfs(root, 0, res); // 使用dfs深度优先遍历binary tree
return res;
}
public void dfs(TreeNode node, int level, List<List<Integer>> res) {
if (node == null) {
return;
}
if (level + 1 > res.size()) { // 层级大于size,才需要新new一个结果
res.add(new ArrayList<>());
}
if (level % 2 == 0) { // 判断是否是zigzag,不是则正序添加,是则倒叙(每次加到最开始的位置)
res.get(level).add(node.val);
} else {
res.get(level).add(0, node.val);
}
dfs(node.left, level + 1, res); // dfs遍历左子树
dfs(node.right, level + 1, res); // dfs遍历右子树
}