7

判断集合相等的高效算法

 2 years ago
source link: https://allenwind.github.io/blog/2860/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Mr.Feng Blog

NLP、深度学习、机器学习、Python、Go

判断集合相等的高效算法

集合是数学上的概念,具有无序、唯一性。两个集合相等是指两个集合中的元素分别相等。那么如何判断集合相等?下面给出四种思路,其中最后一种思路的效率是最高的。

最直接的蛮力方法。对集合中的元素逐一比较。时间复杂度为O(n^2)。

def is_same_set(s1, s2):
if len(s1) != len(s2):
return False
for item1 in s1:
for item2 in s2:
if item1 == item2:
break
else:
continue
else:
# 没有找到元素
return False
return True

for中悬挂的else会在循环没有被break退出时执行,表明元素item1没有在s2中。

第二种思路在第一思路下添加排序,然后位置对应的元素一一比较。时间复杂度为O(nlogn)。

def is_same_set(s1, s2):
s1 = sorted(s1)
s2 = sorted(s2)
for index in range(len(s1)):
if s1[index] != s2[index]:
return False
return True

把集合存储在散列中,判断一个散列是否在集合中使用的时间为O(1)。Python的内置数据结构set采用散列,此处不需要额外的实现。该算法的时间复杂度O(n)。这是最好的算法。不能有时间复杂度的突破,因为扫描集合一遍也有n个元素。

def is_same_set(s1, s2):
if len(s1) != s2:
return False
for item in s1:
if item not in s2:
return False
return True

由于集合具有唯一性(没有相同的元素),当长度相等且s1的元素在s2中都存在,就能保证它们是相等的集合。

可以使用反证法证明。

这是一种完美的思路:采用指纹和。同时,该算法对数据结构有兼容性,即使输入的不是集合而是列表list或元组tuple也可以处理。

假定集合s1拥有元素{e1, e2, …, en}。那么它的指纹和为:
r1 = hash(e1) + hash(e2) + … + hash(en)。使用求和是因为具有交换律,适应集合的无序性。

如果两个集合相同,那么它们的指纹和一定相等(不考虑指纹冲突,因为这是极小概率)

def is_same_set(s1, s2):
r1 = 0
for item1 in s1:
r1 += hash(item1)

r2 = 0
for item2 in s2:
r2 += hash(item2)
return r1 == r2

该实现对输入有兼容性,可以输入list类型、tuple类型、string类型。

当然,上面的实现是有问题的,仅用来做示例。例如:hash函数只能用于不可变类型,如果集合中有可变类型就会出错。在生存环境中应该考虑这样的输入。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK