手撕-图论-并查集与邻接表

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

大厂手撕题目不乏图相关的问题,如何对图有一个很好的认识,以及很好的表示方法是很关键的。

今天正好做了几道题,分享一下代码模板和求解思路,方便回顾与发散思维。

这些题目的主要求解方式为【拓扑排序,并查集,邻接表结合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 =
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值