解法
中心思想是用并查集,关键点是联系的输入
两种方法:
- 枚举list里两两字符串之间的相系,适合词少的时候
- 遍历每个字符,枚举它可能到达的字符,适合词多的时候
假设字符串s可以到达t,注意这里是存的是t到s的边,因为set[i]要存i字符串可以到达的在list里的字符串的集合
点:
- 词稀疏和稠密适合不同的算法
- 注意最后统计的时候同一个s不要统计2次
标准答案里并查集用的是数组下标,我用的是字符串hash,反正也过了,懒得改了
class Solution(object):
def numSimilarGroups(self, A):
"""
:type A: List[str]
:rtype: int
"""
import itertools
f = {}
n = len(A)
if n==0:
return 0
w = len(A[0])
def is_similar(a,b):
l = len(a)
rest = 2
for i in xrange(l):
if a[i]!=b[i]:
rest -= 1
if rest<0:
return False
return rest>=0
def find(x):
if x not in f:
f[x]=x
return x
r = x
while f[r]!=r:
r = f[r]
while x!=r:
tmp = f[x]
f[x] = r
x = tmp
return r
def join(x,y):
f[find(y)]=find(x)
if n<w*w:
for i in xrange(n-1):
for j in xrange(i,n):
if is_similar(A[i],A[j]):
join(A[i],A[j])
else:
from collections import defaultdict
edges = defaultdict(set)
for string in A:
L = list(string)
for j1,j2 in itertools.combinations(xrange(w), 2):
L[j1], L[j2] = L[j2], L[j1]
edges["".join(L)].add(string)
L[j1], L[j2] = L[j2], L[j1]
for string in A:
for word in edges[string]:
join(string, word)
return len(filter(lambda x:x not in f or f[x]==x, set(A)))