大厂手撕题目不乏图相关的问题,如何对图有一个很好的认识,以及很好的表示方法是很关键的。
今天正好做了几道题,分享一下代码模板和求解思路,方便回顾与发散思维。
这些题目的主要求解方式为【拓扑排序,并查集,邻接表结合dfs】,其他内容主要为数据结构中的图结构的表示。
冗余连接
并查集求解:
class Solution {
int[] parent;
public int[] findRedundantConnection(int[][] edges) {
// 并查集问题
int n = edges.length;
parent = new int[1005 + 1];
for(int i=0;i<1005;i++){
parent[i] = i; // 初始化并查集
}
for(int i=0;i<edges.length;i++){
int a = edges[i][0];
int b = edges[i][1];
// 判断这两个点是否已经被加入一个并查集(一棵树)
if(find(a) == find(b))return edges[i];
else insert(a, b);
}
return null;
}
public int find(int a){
if(a == parent[a])return a;
parent[a] = find(parent[a]);
return parent[a];
}
public void insert(int a, int b){
if(find(a) == find(b))return;
parent[find(b)] = a;
}
}
对于并查集的学习,可以看acwing的并查集专项AcWing 836. 合并集合 - AcWing ,我个人觉得很明白。
不过并查集有很多扩展,基础的并查集来说主要包含几个结构
int[] parent; // 父节点数组
int find(int u); // 查找u的根是谁,集合归属判别依据
void insert(int u, int v); // 合并方法
加边法结合宽搜:
我个人是更倾向于参考资料里的【加边法】判别
// 加边法 + bfs
class Solution {
public int[] findRedundantConnection(int[][] edges) {
int n = edges.length;
boolean[] visited = new boolean[n];
List<List<Integer>> graph = new ArrayList<>();
for(int i = 0; i < n; ++i) graph.add(new ArrayList<>());
for(int[] edge : edges){
int u = edge[0] - 1, v = edge[1] - 1;
if(bfs(u, v, visited, graph)) { // 通过 bfs 判断 u, v 是否连通
return new int[]{u + 1, v + 1};
}
graph.get(u).add(v); // 加边 (u, v)
graph.get(v).add(u); // 加边 (v, u)
Arrays.fill(visited, false);
}
return null; // 本题保证必有答案
}
public boolean bfs(int u, int v, boolean[] visited, List<List<Integer>> graph){
Queue<Integer> q = new ArrayDeque<>();
q.add(u);
while(!q.isEmpty()){
u = q.remove();
visited[u] = true;
for(int w : graph.get(u)){
if(w =

本文介绍了如何使用并查集和拓扑排序解决图相关问题,包括寻找冗余连接、判断图中环路以及课程表的安排。文章通过Java代码示例展示了并查集的实现,如并查集的初始化、查找和合并操作,并探讨了邻接表的构建和使用,如ArrayList和HashMap的组合应用。此外,还讲解了如何利用DFS和宽搜判断图的连通性和腐烂橘子的传播问题。
最低0.47元/天 解锁文章
1053

被折叠的 条评论
为什么被折叠?



