839. 相似字符串组(并查集)

一、题目描述

如果交换字符串 X 中的两个不同位置的字母,使得它和字符串 Y 相等,那么称 X 和 Y 两个字符串相似。如果这两个字符串本身是相等的,那它们也是相似的。
例如,“tars” 和 “rats” 是相似的 (交换 0 与 2 的位置); “rats” 和 “arts” 也是相似的,但是 “star” 不与 “tars”,“rats”,或 “arts” 相似。
总之,它们通过相似性形成了两个关联组:{“tars”, “rats”, “arts”} 和 {“star”}。注意,“tars” 和 “arts” 是在同一组中,即使它们并不相似。形式上,对每个组而言,要确定一个单词在组中,只需要这个词和该组中至少一个单词相似。
给你一个字符串列表 strs。列表中的每个字符串都是 strs 中其它所有字符串的一个字母异位词。请问 strs 中有多少个相似字符串组?
示例 1:
输入:strs = [“tars”,“rats”,“arts”,“star”]
输出:2
示例 2:
输入:strs = [“omv”,“ovm”]
输出:1

二、题解
方法一:并查集
我们把每一个字符串看作点,字符串之间是否相似看作边,那么可以发现本题询问的是给定的图中有多少连通分量。

//并查集模板
class UnionFind{
    
    
    private:
        int n;
        int count;
        vector<int> parent;
        vector<int> size;
    public:
        UnionFind(int _n):n(_n),count(_n),parent(_n),size(_n,1){
    
    
            iota(parent.begin(),parent.end(),0);
        }
        int find(int x){
    
    
            return (x==parent[x])?x:parent[x] = find(parent[x]);
        }
        bool merge(int x,int y){
    
    
            x = find(x);
            y = find(y);
            if(x==y) return false;
            if(size[x]<=size[y])   
                parent[x] = y;
            else
                parent[y] = x;
            if(size[x]==size[y])
                size[y]++;
            --count;
            return false;
        }
        bool isConnect(int x,int y){
    
    
            x = find(x);
            y = find(y);
            return x==y;
        }
        int getCount(){
    
    
            return count;
        }
};
class Solution {
    
    
public:
    bool check(string a,string b){
    
    //判断两个字符串是否相似
        if(a==b) return true;
        int index1 = -1;//第一个不相等的位置
        int index2 = -1;//第二个不相等的位置
        for(int i=0;i<a.length();i++){
    
    
            if(a[i]!=b[i]&&index1==-1){
    
    
                index1 = i;
            }
            else if(a[i]!=b[i]&&index2==-1){
    
    
                index2 = i;
            }
            else if(a[i]!=b[i])//如果有超过两个不一样的位置,则返回false
                return false;
        }
        return a[index1]==b[index2]&&a[index2]==b[index1];
    }
    int numSimilarGroups(vector<string>& strs) {
    
    
        int n = strs.size();
        UnionFind uf(n);
        for(int i=0;i<n;i++){
    
    
            for(int j=i+1;j<n;j++){
    
    
                if(uf.isConnect(i,j))//先判断当前这对字符串是否已经连通
                    continue;
                if(check(strs[i],strs[j])){
    
    //如果两个字符串相似,则合并
                    uf.merge(i,j);
                }  
            }
        }
        return uf.getCount();//返回连通个数即为所求
    }
};

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_38748148/article/details/113461778
今日推荐