广度优先搜索
Posted 浮云神码
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了广度优先搜索相关的知识,希望对你有一定的参考价值。
这是关于广度优先搜索的第二遍文章,本次会分享两个LeetCode题目。和上一篇使用队列来实现广度优先搜索的方式不同,本次使用到了栈来实现广度优先搜索。
103. 二叉树的锯齿形层序遍历
import java.util.*;
/**
* https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal
* 103. 二叉树的锯齿形层序遍历
* 难度 中等
* 给定一个二叉树,返回其节点值的锯齿形层序遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。
*
* 例如:
* 给定二叉树[3,9,20,null,null,15,7],
*
* 3
* / \
* 9 20
* / \
* 15 7
* 返回锯齿形层序遍历如下:
*
* [
* [3],
* [20,9],
* [15,7]
* ]
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode-cn.com/problems/binary-tree-zigzag-level-order-traversal
*/
public class ZigZagLevelOrderTree {
public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();
if (root == null) {
return result;
}
/**
* 利用栈【先进后出】的特性来实现二叉树的锯齿形遍历
* 两个栈
* 1. 从左向右遍历的栈
* 2. 从右向左遍历的栈
*/
Stack<TreeNode> leftToRightStack = new Stack<>();
Stack<TreeNode> rightToLeftStack = new Stack<>();
leftToRightStack.add(root);
while(!leftToRightStack.isEmpty() || !rightToLeftStack.isEmpty()) {
// 每次遍历只有一个栈中存在数据, 下面的代码保证了这一点
boolean leftFlag = !leftToRightStack.isEmpty();
List<Integer> currentLevelList = new ArrayList<>();
if (leftFlag) {
while (!leftToRightStack.isEmpty()) {
// leftToRightStack每pop一条数据, 就将左子节点、右子节点依次压入rightToLeftStack中
// 这样在处理rightToLeftStack时, 就可以从右向左处理节点了
TreeNode current = leftToRightStack.pop();
if (current.left != null) {
rightToLeftStack.push(current.left);
}
if (current.right != null) {
rightToLeftStack.push(current.right);
}
currentLevelList.add(current.val);
}
} else {
while (!rightToLeftStack.isEmpty()) {
// 同理, rightToLeftStack每pop一条数据, 就将右子节点、左子节点依次压入leftToRightStack中
// 这样在处理leftToRightStack时, 就可以从左向右处理节点了
TreeNode current = rightToLeftStack.pop();
if (current.right != null) {
leftToRightStack.push(current.right);
}
if (current.left != null) {
leftToRightStack.push(current.left);
}
currentLevelList.add(current.val);
}
}
result.add(currentLevelList);
}
return result;
}
}
107. 二叉树的层序遍历 II
import java.util.*;
/**
* https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii
* 107. 二叉树的层序遍历 II
* 给定一个二叉树,返回其节点值自底向上的层序遍历。(即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)
*
* 例如:
* 给定二叉树 [3,9,20,null,null,15,7],
*
* 3
* / \
* 9 20
* / \
* 15 7
* 返回其自底向上的层序遍历为:
*
* [
* [15,7],
* [9,20],
* [3]
* ]
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal-ii
*/
public class LevelOrderBottomTree {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
List<List<Integer>> result = new ArrayList<>();
if (root == null) {
return result;
}
/**
* 使用栈临时存储结果, 按照先进后出的规则, 后面将栈元素依次取出存入最终结果即可
*/
Stack<List<Integer>> tempResult = new Stack<>();
/**
* 以下步骤就和【102. 二叉树的层序遍历】一样
* 广度优先搜索 借助【队列】来实现
*/
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
while (!queue.isEmpty()) {
/**
* size为当前队列的长度(即当前层级的元素个数), 有以下两个作用
* 1. 设置存储最终结果的List的长度
* 2. 决定for循环的次数, 初始长度决定了本次while循环应该获取多少个元素
*/
int size = queue.size();
List<Integer> levelList = new ArrayList<>();
for (int i = 0; i < size; i++) {
TreeNode current = queue.remove();
// 将当前元素的左右子节点依次加入队列, 实现从左到右访问
if (current.left != null) {
queue.add(current.left);
}
if (current.right != null) {
queue.add(current.right);
}
levelList.add(current.val);
}
tempResult.push(levelList);
}
// 最终将栈临时存储的数据添加到最终的结果list中
while (!tempResult.isEmpty()) {
result.add(tempResult.pop());
}
return result;
}
}
以上是关于广度优先搜索的主要内容,如果未能解决你的问题,请参考以下文章