## Strategy:
## Use union-find to group similar strings
## Count number of distinct groups
## Time: O(L_str*N_strs^2)
## Space: O(N_strs)
## where:
## N_strs is the number of strings
## L_str is the length of a string
class Solution:
def numSimilarGroups(self, strs: List[str]) -> int:
N_strs = len(strs)
uf_parents = [x for x in range(N_strs)]
def uf_get_parent(idx):
if idx == uf_parents[idx]:
return idx
p = uf_get_parent(uf_parents[idx])
uf_parents[idx] = p
return p
def uf_union(idx_1, idx_2):
p_1 = uf_get_parent(idx_1)
p_2 = uf_get_parent(idx_2)
uf_parents[p_1] = p_2
def uf_flatten ():
for idx in range(N_strs):
uf_parents[idx] = uf_get_parent(idx)
def are_similar (s_1, s_2):
result = True
swap_made = None
prev_mismatch = None
for idx in range(len(s_1)):
if s_1[idx] != s_2[idx]:
if swap_made:
result = False
break
elif prev_mismatch is None:
prev_mismatch = (s_1[idx],s_2[idx])
result = False
else:
if (s_2[idx],s_1[idx]) == prev_mismatch:
swap_made = True
result = True
else:
result = False
break
return result
for idx_1 in range(N_strs):
for idx_2 in range(idx_1+1,N_strs):
if are_similar(strs[idx_1], strs[idx_2]):
uf_union(idx_1, idx_2)
uf_flatten()
return len(set(uf_parents))