Leetcode LCR 116. 省份数量 并查集

171 阅读2分钟

LCR 116. 省份数量 - 力扣(LeetCode)

我们利用上一篇文章里面模拟实现的并查集来写这道题:并查集理论篇 - 掘金 (juejin.cn)

思想

首先就是判断是否i,j两个城市是否连痛,如果连通说明处于可以合并为一个集合。

class UnionFindSet
{
public:
	UnionFindSet( size_t n)
		:_ufs(n, -1)
	{}


	void Union(int x1,int x2)//合并集合
	{
		int root1 = Findroot(x1);
		int root2 = Findroot(x2);
		if (root1 == root2)return;//如果根相同,说明是一个根,即在一个集合,无需再合并
		else
		{
			_ufs[root1] += _ufs[root2];//根加上孩子节点的编号
			_ufs[root2] = root1;//孩子节点存储父节点的下标,以便找到父节点
		}
	}



	int Findroot(int x)//找根节点
	{
		int parent = x;
		while (_ufs[parent] >= 0)//说明不是根
		{
			parent = _ufs[parent];//跳到x的编号的存的下标的位置
		}
		return parent;
	}



    bool Inser(int x1,int x2)//判断a,b集合是否在一个集合
	{
		return Findroot(x1) == Findroot(x2);
	}

	size_t Setsize()//判断一个并查集有多少个集合
	{
		size_t size = 0;
		for (size_t i = 0; i < _ufs.size(); i++)
		{
			if (_ufs[i] < 0)size++;//只要根节点的编号才为负值
		}
		return size;
	}


private:
	vector<int> _ufs;//编号找人
};


class Solution {
public:
    int findCircleNum(vector<vector<int>>& isConnected) {
    UnionFindSet ufs(isConnected.size());//初始化isConnected.size()个元素,在我们的上面实现的并查集里全部初始化为-1了,即刚开始都是独立的集合
    
    //遍历整个isConnected数组
     for(size_t i=0;i<isConnected.size();i++)
     {
         for(size_t j=0;j<isConnected.size();j++)
         {
             if(isConnected[i][j]==1)ufs.Union(i,j);//如果可以连通就合并为一个集合
         }
     }
     return ufs.Setsize();//返回集合的个数
    }
};

第二种

class Solution {
public:
    int findCircleNum(vector<vector<int>>& isConnected) {
    vector<int> ufs(isConnected.size(),-1);//初始化为-1,表示独立集合
    
    //找根
    auto findRoot=[&ufs](int x)
    {
       while(ufs[x]>=0)//编号为正数,说明不是根
           x=ufs[x];//跳到编码对应的下标,即其父节点
        return x;
    };
     for(size_t i=0;i<isConnected.size();i++)
     {
         for(size_t j=0;j<isConnected.size();j++)
         {
             if(isConnected[i][j]==1)
             {
                  int root1=findRoot(i);
                  int root2=findRoot(j);
                  if(root1==root2)continue;
                  else 
                  {
                      ufs[root1]+=ufs[root2];
                      ufs[root2]=root1;
                  }
             }
         }
     }
     int n=0;
     for(auto e:ufs)
     {
         if(e<0)n++;//小于0说明未合并,是独立集合
     }
     return n;//返回独立集合的个数
    }
};