(一)图

(一)图

基本方法

DFS

运用递归,深度优先遍历。

代码框架为:

    void dfs(int u) {
        //对当前节点进行操作
        for (int v: edges[u]) {//遍历当前节点的邻居
            //(如果未遍历过)递归DFS
                dfs(v);
        }
        //对当前节点后续操作
    }

时间复杂度: O ( n + m ) O(n+m) O(n+m)

空间复杂度: O ( n + m ) O(n+m) O(n+m),其中 O ( m ) O(m) O(m)为存储所有边需要的空间, O ( n ) O(n) O(n)为深度优先搜索中使用的栈空间。

BFS

利用队列迭代操作,广度优先遍历。

代码框架为:

        queue<int>q;
        q.push(i);//初始化队列
        while(!q.empty()){
            int u=q.front();
            q.pop();
            //取出队首元素,操作
            for(auto v:edges[u]){//遍历队首元素的每一条边
                //相应操作
                //(if...)子节点入队
                    q.push(v);
            }
        }

时间复杂度: O ( n + m ) O(n+m) O(n+m)

空间复杂度: O ( n + m ) O(n+m) O(n+m)。为了对图进行广度优先搜索,我们需要存储成邻接表的形式,空间复杂度为 O ( n + m ) O(n+m) O(n+m)。在广度优先搜索的过程中,我们需要最多 O ( n ) O(n) O(n) 的队列空间(迭代)进行广度优先搜索。因此总空间复杂度为 O ( n + m ) O(n+m) O(n+m)

并查集

主要操作:(加权)并+(压缩路径)查

代码框架为:

class UnionFind{
public:
    vector<int>parent;
    vector<int>size;
    int setcount;
public:
    UnionFind(int n){
        setcount=n;
        parent.resize(n);
        for(int i=0;i<n;i++)
        {
            parent[i]=i;
        }
        size.resize(n,1);
    }
    int findset(int x){
        return parent[x]==x?x:findset(parent[x]);
    }
    bool unite(int x,int y){
        int rx=findset(x);
        int ry=findset(y);
        if(rx==ry)
        return false;
        if(size[rx]<size[ry])
            swap(rx,ry);
        parent[ry]=rx;
        size[rx]+=size[ry];
        setcount--;
        return true;
    }
    bool connected(int x,int y){
        return findset(x)==findset(y);
    }
};

时间复杂度: O ( m ⋅ α ( n ) ) O(m \cdot \alpha(n)) O(mα(n)),其中 α \alpha α 是阿克曼函数的反函数。

空间复杂度: O ( n ) O(n) O(n),即为并查集需要使用的空间。

应用

岛屿类问题

网格类问题DFS通用思路

判断base case+访问相邻节点

避免重复遍历→状态标记数组

连通性

天然并查集(DFS也可以)

拓扑排序

DFS/BFS

  • DFS

    对于每个节点有未搜索,搜索中,已搜索三个状态,u是v的先修课程也就是v→u。初始化未搜索,选择一个节点进行DFS变成搜索中,当一个节点所有子节点都完成搜索后它变成已搜索,入栈。如果它的子节点有搜索中,则说明有环,无法拓扑排序。拓扑排序结果就是从栈底到栈顶的序列。

  • BFS

    u是v的先修课程也就是u→v,将每个入度为0的点入队,每次把队首节点加入答案时,它决定的其他节点入度减一,更新队列。迭代操作直到队伍为空,如果答案中节点数目等于课程数目则说明能拓扑排序。

相关力扣练习

个人笔记

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值