算法练习大厂高频「广度优先搜索」类型题目总结
Posted 在路上的德尔菲
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法练习大厂高频「广度优先搜索」类型题目总结相关的知识,希望对你有一定的参考价值。
题目一:二叉树的层序遍历
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
示例:
输入:[3,9,20,null,null,15,7],
3
/ \\
9 20
/ \\
15 7
输出:
[
[3],
[9,20],
[15,7]
]
题解:
层序遍历符合先进先出模型(FIFO),所以适合使用队列。
注意需要2次循环,外循环是判断总体是否还有节点,内循环判断每一层是否还有节点。
另外用size--
的方式相比使用start
和end
来控制输出每层节点方便。
public List<List<Integer>> levelOrder(TreeNode root) {
Queue<TreeNode> queue = new LinkedList<>();
List<List<Integer>> res = new ArrayList<>();
queue.offer(root);
while (!queue.isEmpty()) {
int size = queue.size();
List<Integer> list = new ArrayList<>();
while (size-- > 0) {
TreeNode node = queue.poll();
if (node.left != null) queue.offer(node.left);
if (node.right != null) queue.offer(node.right);
list.add(node.val);
}
res.add(list);
}
return res;
}
- 时间复杂度:O(N),N为节点个数,每个节点进队列出队列一次。
- 空间复杂度:O(N),队列中元素个数不超过N个。
相关题目扩展:
103 二叉树锯齿形层序遍历在这里插入代码片
107二叉树的层序遍历II
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-level-order-traversal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
校招美团二面算法题
题目二:二叉树的右视图
给定一棵二叉树,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。
示例:
输入: [1,2,3,null,5,null,4]
输出: [1, 3, 4]
解释:
1 <---
/ \\
2 3 <---
\\ \\
5 4 <---
和第一题解题思路类似,都是需要层序遍历,找到每层的最后一个节点。
注意不用2次循环,因为每层只用找到最右一个节点加入返回结果中,不像第一题要把每层所有节点都加入到返回结果中。
题解:
public List<Integer> rightSideView(TreeNode root) {
List<Integer> res = new ArrayList<>();
if (root == null) return res;
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
int start = 0, end = 1;
while (!queue.isEmpty()) {
TreeNode node = queue.poll();
start++;
if (node.left != null) {
queue.add(node.left);
}
if (node.right != null) {
queue.add(node.right);
}
//判断是否为每层的最后一个节点
//start置0,end 为当前层存在的节点个数
if (start == end) {
start = 0;
end = queue.size();
res.add(node.val);
}
}
return res;
}
- 时间复杂度:O(N),N为节点个数,每个节点进队列出队列一次。
- 空间复杂度:O(N),队列中元素个数不超过N个。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/binary-tree-right-side-view
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题目三:二叉树的最小深度
给定一个二叉树,找出其最小深度。
最小深度是从根节点到最近叶子节点的最短路径上的节点数量。
说明:叶子节点是指没有子节点的节点。
输入:root = [3,9,20,null,null,15,7]
3
/ \\
9 20
/ \\
15 7
输出:2
首先我们需要自定义一个模型,模型中包括原节点TreeNode
和节点的深度。
核心思路为当我们找到一个叶子节点,即左子树和右子树均为null
,返回这个叶子节点的深度,结束查找。
如果当前节点存在左子树节点,将左子树节点模型放入队列中,同理如果当前节点存在右子树节点,将右子树节点模型放入队列中,注意子树模型中高度要加1。
解题:
class NodeDep {
TreeNode node;
int depth;
public NodeDep(TreeNode node, int depth) {
this.node = node;
this.depth = depth;
}
}
public int minDepth(TreeNode root) {
if (root == null)return 0;
Queue<NodeDep> queue = new LinkedList<>();
queue.offer(new NodeDep(root, 1));
while (!queue.isEmpty()) {
NodeDep pollNode = queue.poll();
if (pollNode.node.left == null && pollNode.node.right == null) return pollNode.depth;
if (pollNode.node.left != null) queue.offer(new NodeDep(pollNode.node.left, pollNode.depth + 1));
if (pollNode.node.right != null) queue.offer(new NodeDep(pollNode.node.right, pollNode.depth + 1));
}
return 0;
}
- 时间复杂度:O(N),N为节点个数,每个节点进队列出队列一次。
- 空间复杂度:O(N),队列中元素个数不超过N个。
此题递归算法见【算法总结】二叉树常见算法题目及解题思路汇总
题目四:01矩阵
给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。
两个相邻元素间的距离为 1 。
示例:
输入:
[[0,0,0],
[0,1,0],
[1,1,1]]
输出:
[[0,0,0],
[0,1,0],
[1,2,1]]
记住以下思路:
对于 「Tree 的 BFS」 (典型的「单源 BFS」)
首先把 root 节点入队,再一层一层无脑遍历就行了。
对于 「图 的 BFS」 (「多源 BFS」) 做法其实也是一样滴~,与 「Tree 的 BFS」的区别注意以下两条就 ok 辣~
Tree 只有 1 个 root,而图可以有多个源点,所以首先需要把多个源点都入队;
Tree 是有向的因此不需要标识是否访问过,而对于无向图来说,必须得标志是否访问过哦!并且为了防止某个节点多次入队,需要在其入队之前就将其设置成已访问!避免超时
题解:
- 1.定义一个队列,里面存放遍历的节点的位置信息 Queue<int[]>
- 2.先找到所有0的节点放进队列,其他节点标记为-1
- 3.对队列中每个节点的上下左右节点进行判断,首先是符合边界条件,其次是符合没有被访问过(值为-1)
- 4.距离为在基础点距离上加1,即mat[xNew][yNew] = mat[x][y] + 1
- 5.将这个值放入队列中,循环第3步
public int[][] updateMatrix(int[][] mat) {
Queue<int[]> queue = new LinkedList<int[]>();
int n = mat.length, m = mat[0].length;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (mat[i][j] == 0) {
queue.offer(new int[]{i, j});
} else {
mat[i][j] = -1;
}
}
}
//为了构建上下左右四个点方便
int[] dx = {-1, 1, 0, 0};
int[] dy = {0, 0, -1, 1};
while (!queue.isEmpty()) {
int[] poll = queue.poll();
int x = poll[0], y = poll[1];
for (int i = 0; i < 4; i++) {
int xNew = x + dx[i];
int yNew = y + dy[i];
if (xNew >= 0 && xNew < mat.length && yNew >= 0 && yNew < mat[0].length && mat[xNew][yNew] == -1) {
mat[xNew][yNew] = mat[x][y] + 1;
queue.offer(new int[]{xNew, yNew});
}
}
}
return mat;
}
- 时间复杂度:O(n*m),每个节点进队列出队列一次。
- 空间复杂度:O(n*m),原地修改原输入数据来存储结果,每个节点都会进入队列。
相关题目扩展:
地图分析1162
以上是关于算法练习大厂高频「广度优先搜索」类型题目总结的主要内容,如果未能解决你的问题,请参考以下文章