python中的幂函数,python幂运算函数
昨天看到有人在TL里说了一个面试问题:不用递归找到一个固定集合中的所有子集。按照@miloyip的说法,这是一个幂集的问题,中文叫幂集。这次中学数学学的,但是真的没想过怎么用计算机求幂集,就干脆找算法求幂集。根据维基上的介绍和我自己的理解(http://en . Wikipedia . org/wiki/Power _ set),给定一个包含n个元素的集合S,我用python实现了三种计算幂集的算法。除非另有说明,下面的并集是指取两个集合的并集。
1.利用二进制数和幂集的对应关系。
取[0,2 (n-1)]整数区间内的任意值x,x的二进制表示可以用来表示s的一个子集:对于x的第I位,如果为1,则这个子集包含s的第I个元素,否则不包含。所以只要遍历[0,2 (n-1)]的整数区间,就可以列出S的所有子集,这些子集的集合就是S的幂集,银耳汤的自信老板也指出了这个方法。代码如下:
defpower_set:
n=透镜
测试标记=[1
forkinrange(0,2**n):
l=[]
foridx,iteminenumerate(test_marks):
ifkitem:
附加(s[idx])
屈服集
#Asimpletest
def__test__():
s=[1,2,3,4]
foreinpower_set:
打印机
__测试_ _()
2.递归计算和一种改进的非递归算法。
在wiki上给出了递归算法。总的思路是先取出S中的一个元素E,然后求出S中其他元素组成的集合的幂集,再将E与求出的幂集的每个组合进行组合,求出结果集。因此,可以列出所有可能的子集。这个算法的某些子集在枚举时可能会重复出现,所以我没有用yield,而是直接返回了一个list。代码如下:
#simplyaddasetstolistl,withduplicatecheck
defadd_set_to_list(l,s):
ifsnotinl:
l .追加
#F(e,T)={xunion{e}xbelongstoT}
defF(e,T):
l=[]
添加集合到列表(l,e)
forxinT:
y=ex
add_set_to_list(l,y)
returnl
defpower_set:
l=[]
ifnots:#emptyset
l.append(set())
returnl
外来者:
es=set((e,))
t=s-es
s2=功率设置(t)
foriins2:
add_set_to_list(l,I)
foriinF(es,s2):
add_set_to_list(l,I)
returnl
上述算法有两个缺点:一是在计算过程中会重复生成一些集合,因此存在重复计算;二是递归,效率可能不高。和@GiantIron讨论后得出一个非递归算法。思路和上面的递归算法类似,但有区别,代码简单很多。非递归算法的数学描述如下:
给定一个集合s,其幂集表示为p (s),那么对于一个元素e,p (s并{e}}=p (s)并f (e,P(s))。直观地说,给定集合S及其幂集P(s),如果给S增加一个新元素E,则形成的新集合的幂集是P(s)和F(e,P(s))的并集。f()函数已经在递归算法的实现中给出。上面的描述其实和递归算法差不多,但是我们可以用这个关系来增量计算,而不是递归。
代码如下。l用于保存按增量计算的功率集。由于后面的计算依赖于前面计算的结果,所以这里不使用yield,直接返回一个列表。因为这个计算过程中不会出现重复的子集,所以union的运算直接被list.extend()代替。同样,在递归算法中f()函数的实现中,有一个检查是否是重复元素的操作,但在这里其实是不必要的:
defpower_set:
l=[set(),]
外来物:
l.extend(F(set((e,),l))
returnl
3.s={subsets(s,k) k=0,1,2,n}
其中subsets(s,k)表示s的所有模都是k的子集,即它包含k个元素。这种关系显而易见。因此,很容易找到子集(s,k)。寻找子集(s,k)的代码不是我自己写的。下面是一个实现,也是递归的。它利用了幂集与二项式系数的关系和帕斯卡法则(其实和杨辉三角形描述的关系是一样的),看起来非常漂亮。代码如下,其中k_subsets(s,k)是其他人实现的子集(s,k)的函数。
defpower_set:
forkinrange(0,len(s) 1):
fork_setink_subsets(s,k):
yieldk_set
除了以上方法,信心满满的银耳汤老板还介绍了使用stl的next _ permutaion()生成组合数(链接)然后求幂集。我觉得这种方法和上面提到的第三种方法类似,都是利用了组合和幂集的关系,只是生成组合的方法不同。我相信有更多的方法可以解决这个问题。
解决同一个问题的方法有很多种,但要正确解决一个看似简单的问题,却不是那么容易。因为python本身提供了对set的支持,所以实现幂集要容易得多。但是set对象本身不能作为集合的元素,这是需要考虑的,而且我对python也不熟悉。
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。