leetcode 839 Similar String Groups

题目

Two strings X and Y are similar if we can swap two letters (in different positions) of X, so that it equals Y.

We are given a list A of strings. Every string in A is an anagram of every other string in A. How many groups are there?

anagram 这个词的意思被忽略导致我误理解了题意

Intuition

我们可以在 Ow 的时间内分辨 两个words 是否相似

一种思想是纯使用暴力算法 : n2W 的时间内判断两个单词是否详细

另一种想法是 枚举一个单词的所有相似紧邻 一个单词之多有 C2w 个紧邻

W2 的时间用来枚举所有的可能相似单词 W 时间
这样我们可以使用 ONW3 的时间 列出所有的单词相邻
py2 版本

class DSU(object,N):
    def __init__(self):
        self.par=range(N)
    def find(self,x):
        if(self.par[x]!=x):
            self.par[x]= self.find(par[x])
            return self.par[x]
    def union(self,x,y):
        if(x!=y):
            self.par[self.find(x)]=self.find(y)
class Solution(object):
    def numSimilarGroups(self,A):
        N,w=len(A),len(A[0])   # 分别是词的个数和 词的长度
        def similar(W1,W2):
            diff=0
            for x,y in itertools.izip(W1,W2):
                if x!=y:
                    diff=dfif+1
            return diff <=2
        
        dsu=DSU(N)

        if(N<W*W): //如果整个词列表较短, 遍历整个词列表进行计算会更快
            for (i1,word1),(i2,word2) in itertools.combinations(enumerate(A),2):#高效的枚举操作 ,也是py支持的非常有用的操作
                if similar(word1,word2):
                    dsu.union(i1,i2)  #使用编号作为合并的索引
        else:
            buckets=collections.defaultdict(set) # values 是set 且具有默认值的字典
            for i,word in enumerate(A):
                L=list(word) # string 调换中间某几个字符顺序的最佳操作
                for j0,j1 in itertools.combinations(xrange(N),2):   组合操作的最佳方式 使用itertools 
                    L[j0], L[j1] = L[j1], L[j0]
                    buckets["".join(L)].add(i)
                    L[j0], L[j1] = L[j1], L[j0]
            for i1, word in enumerate(A):
                for i2 in buckets[word]:
                    dsu.union(i1, i2)                                             
             return sum([for dsu.par[x]==x for x in range(N)]) #并查集变通块数量的查询简易方法

以上的代码虽然正确,但是复杂度高 ,不能通过(py3 的方式重写之后 不能通过py3 的测试)
下面是 加速版本

class Solution:
    def numSimilarGroups(self, A):
        SA = set(A)  # to delete duplicate items
        A = list(SA) # make it indexable
        L = len(A)
        base = [i for i in range(L)]
        
        def find(x):
            if base[x] != x:
                base[x] = find(base[x])
            return base[x]
        
        def union(x, y):
            base[find(x)] = find(y)
            
        def check(x, y):
            return sum(a!=b for a, b in zip(A[x], A[y])) == 2
        
        if L < len(A[0])**2:  # deal with long word with few items
            for i1, i2 in itertools.combinations(range(L), 2):
                if check(i1, i2):
                    union(i1, i2)
        else: # deal with short word with lots of items
            buckets = collections.defaultdict(set)
            for i, word in enumerate(A):
                for i1, i2 in itertools.combinations(range(len(word)), 2):
                    if word[i1] != word[i2]:  # filter, otherwise it will exceed memory limit
                        wl = list(word)
                        wl[i1], wl[i2] = wl[i2], wl[i1]
                        key = "".join(wl)
                        if key in SA:
                            buckets[key].add(i)

            for i, word in enumerate(A):
                for j in buckets[word]:
                    union(i, j)
                    
        return sum(base[x] == x for x in range(L))

可以看到 这里将dsu 单独拿出来使用,
然后在枚举 一个单词的所有邻居的时候 也进行了优化 就是如果这个单词的两个位置不一样 我们才认为是一个合法的邻居。

猜你喜欢

转载自www.cnblogs.com/sfzyk/p/9250477.html