Leetcode---并查集

  

简介

             并查集是一种数据结构,一般它处理的是图(其实是解决无向图的)的连通分量问题,但是当并查集的根节点可以维护更多的信息时,并查集可以解决范围更广的基于无向图连通分量的问题。做了这么多并查集的题目后,我感觉并查集就是解决有关物与物之间的关系问题的数据结构且这种关系还必须是可传递的关系,所以一般遇到这种问题可以先尝试用并查集解决。

并查集操作比较简单,主要是理解路径压缩、按值归并、带权并查集就ok了。

 

题目

         547. 朋友圈(求无向图连通分量)

684. 冗余连接(无向图、连通分量)

685. 冗余连接 II(上一题的改编)

839. 相似字符串组(无向图、连通分量)

面试题 17.07. 婴儿名字(按秩归并)

200. 岛屿数量(解决一种DFS经典水洼问题)


 

547. 朋友圈(求无向图连通分量)

class Solution {
public:

    //并查集操作
    int fa[11111];
    int Find(int x){return fa[x]<0?x:fa[x] = Find(fa[x]);}
    bool Union(int x,int y)
    {
        int rx = Find(x), ry = Find(y);
        if(rx == ry)return false;
        fa[rx] = ry;
        return true;
    }

    int findCircleNum(vector>& M) {
        memset(fa,-1,sizeof fa);

        int n = M.size();    
        if(!n) return 0;
        int m = M[0].size();

        for(int i = 0;i>& M) {
        int n = M.size();
        if(!n) return 0;
        int m = M[0].size();
        
        vector vis(n+1,false);
        int ans = 0;

        for(int i = 0;i>&M,vector&vis,int i)
    {
        if(vis[i]) return;
        vis[i] = true;
        
        for(int j = 0;j

 

 

684. 冗余连接(无向图、连通分量)

class Solution
{
    public:
    
    int fa[11111];
    int Find(int x){return fa[x]<0?x:fa[x] = Find(fa[x]);}
    bool Union(int x,int y)
    {
        int rx = Find(x), ry = Find(y);
        if(rx == ry)return false;
        fa[rx] = ry;
        return true;
    }

    vector findRedundantConnection(vector>& edges) {
        memset(fa,-1,sizeof fa);
        int n = edges.size();

        for(int i = 0;i{};
    }
};

 

685. 冗余连接 II(上一题的改编)

class Solution {
public:
    

    int fa[11111];
    int Find(int x){return fa[x]<0?x:fa[x] = Find(fa[x]);}
    bool Union(int x,int y)
    {
        int rx = Find(x), ry = Find(y);
        if(rx == ry)return false;
        fa[rx] = ry;
        return true;
    }

    vector check(vector>& edges,int except)
    {
        memset(fa,-1,sizeof fa);
        for(int i = 0;i findRedundantDirectedConnection(vector>& edges) {
        
        int n = edges.size();    
        std::vector degree(n+11,0);
        for(auto &x:edges) ++degree[x[1]];

        for(int i = n-1;i>=0;--i)
        {
            if(degree[edges[i][1]] == 2 && !check(edges,i).size())
            {//倒叙找出入度为2的点,不带这条边是否符合题意,如果符合,则返回这条边
                return edges[i];
            }
        }
        return check(edges,n);

    }
};

 

 

 

839. 相似字符串组(无向图、连通分量)

class Solution {
public:
    bool isSame(string &a,string &b)
    {
        int n = a.size(),m=b.size();
        if(n != m) return false;
        int cnt = 0;
        for(int i = 0;ifa;

    int Find(int x)
    {
        return x == fa[x]? x: fa[x] = Find(fa[x]);
    }
    
    void Union(int x,int y)
    {
        int fx=Find(x),fy = Find(y);
        if(fx == fy)return;
        fa[fx] = fy;
    }

    int numSimilarGroups(vector& A) {
        int n = A.size();
        fa.resize(n);
        for(int i = 0;i

 

面试题 17.07. 婴儿名字(按秩归并)

class Solution {
public:

    unordered_map fa;//并查集关系
    unordered_map mp;//并查集权值:集合大小
  //  unordered_map mp;

    string Find(string x)
    {
        return fa[x] == x?x:fa[x] = Find(fa[x]);
    }

    void Union(string x,string y)
    {
        string fax = Find(x);
        string fay = Find(y);
        if(fax == fay)return;
        if(fax trulyMostPopular(vector& names, vector& synonyms) {
       
        for(auto x:names)
        {//初始化
            int pos = x.find("(");
            string name = x.substr(0,pos);
           int pos2 = x.find(")");
            string fre = x.substr(pos+1,pos2-pos+1);
            mp[name] = stoi(fre);
            fa[name] = name;

        }
        for(auto x:synonyms)
        {//初始化
            int pos = x.find(",");
            int pos2 = x.find(")");
            int sz = x.size();
            string name1 = x.substr(1,pos-1);
            string name2 = x.substr(pos+1,sz-1-pos-1);
            fa[name1] = name1;
            fa[name2] = name2;
        }

        for(auto x:synonyms)
        {//合并
            int pos = x.find(",");
            int pos2 = x.find(")");
            int sz = x.size();
            string name1 = x.substr(1,pos-1);
            string name2 = x.substr(pos+1,sz-1-pos-1);
            // fa[name1] = name1;
            // fa[name2] = name2;
            Union(name1,name2);
        }

        vectorans;
        for(auto x:fa)
        {
            if(x.first == x.second)
            {
                string s = x.first + "(" + to_string(mp[x.first]) + ")" ;
                ans.push_back(s);
            }
        }
        return ans;


    }

};

 

 

 

200. 岛屿数量(解决一种DFS经典水洼问题)

class Solution {
public:

    //并查集操作
    int fa[111111];
    int Find(int x){return fa[x]<0?x:fa[x] = Find(fa[x]);}
    bool Union(int x,int y)
    {
        int rx = Find(x), ry = Find(y);
        if(rx == ry)return false;
        fa[rx] = ry;
        return true;
    }
     int d[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
    int numIslands(vector>& grid) {
        int n = grid.size();
        if(!n)return 0;

        int m = grid[0].size();
        memset(fa,-1,sizeof fa);

        for(int i = 0;i=n||dy<0||dy>=m)continue;
                        if(grid[dx][dy] == '1')Union(i*m+j,dx*m+dy);
                    }
                }
            }
        int ans = 0;
        for(int i = 0;i>& M) {
         int n = M.size();
        if(!n) return 0;
        int m = M[0].size();
        
        int ans = 0;
        for(int i = 0;i>&M,int i,int j,int n,int m)
    {
        if(i>=n || i<0 || j>=m || j<0)return;
        if(M[i][j] != '1')return;
        
        M[i][j] = '0';
        dfs(M,i+1,j,n,m);
        dfs(M,i-1,j,n,m);
        dfs(M,i,j-1,n,m);
        dfs(M,i,j+1,n,m);
    }
};

 

你可能感兴趣的:(LeetCode,&&,基础算法总结)