python求幂集_求幂集的算法 - Sethylar的个人页面 - OSCHINA - 中文开源技术交流社区...
昨天看到有人在TL里说一个面试题 : 不用递归法 求一个固定集合内的所有子集。经 @miloyip 指出,这是个power set 的问题,在中文中称为幂集。这个中学数学里就学过了,不过如何用计算机求幂集还真没考虑过,就索性找了找求幂集的算法。根据wiki上的介绍和我自己的理解( http://en.wikipedia.org/wiki/Power_set),给定一个包含n个元素的集合s,我用python实现了三种计算幂集的算法。如果没有额外说明,下文中的 union表示取两个集合的合集。
1. 利用二进制数与幂集之间的对应关系
在[0,2^(n-1)]的整数区间上任取一个值x,x的二进制表示可以用来表示s的一个子集:对于x的第i位,如果为1,则此子集包含s的第i个元素,否则不包含。因此,只要遍历 [0,2^(n-1)]的整数区间,就能列举出s的所有子集,这些子集的集合就是s的幂集。这个方法陈硕老大也指出来了。代码如下:
def power_set(s):
n = len(s)
test_marks = [ 1<
for k in range(0, 2**n):
l = []
for idx, item in enumerate(test_marks):
if k&item:
l.append(s[idx])
yield set(l)
#A simple test
def __test__():
s = [1,2,3,4]
for e in power_set(s):
print e
__test__()
2. 递归计算和一个改进的非递归算法
wiki上给出了一个递归的算法,大致思想是先取出s中的一个元素e,然后求s中其他元素组成的集合的幂集,再把e与求出的幂集中的每个结合进行组合求合集,因此能列举出所有可能的子集。这个算法在列举过程中某些子集可能会重复出现,因此我没有用yield,而是直接返回了一个list。代码如下:
#simply add a set s to list l, with duplicate check
def add_set_to_list(l, s):
if s not in l:
l.append(s)
#F(e, T) = {x union {e} | x belongs to T}
def F(e, T):
l = []
add_set_to_list(l, e)
for x in T:
y = e | x
add_set_to_list(l, y)
return l
def power_set(s):
l = []
if not s: #empty set
l.append(set())
return l
for e in s:
es = set((e,))
t = s - es
s2 = power_set(t)
for i in s2:
add_set_to_list(l, i)
for i in F(es, s2):
add_set_to_list(l, i)
return l
上面这个算法有两个缺点:一是计算过程中会重复生成某些集合,因此 有重复计算,二是它是递归的,效率上可能不高。经过与 @GiantIron 讨论,得到了一种非递归算法,思想跟上面的递归算法类似,但又有区别,而代码要简单得多。非递归算法的数学描述如下:
给定一个集合s,它的幂集表示为P(s), 则对于一个元素e, P( s union {e} } = P(s) union F(e, P(s))。直观地说,已知集合s和它的幂集P(s),如果往s中加入一个新元素e,则形成的新的集合的幂集是 P(s) 和 F(e, P(s)) 的合集。其中F()函数在递归算法的实现中已经给出。上述描述其实跟递归算法中类似,但是我们可以利用这个关系来增量地计算,而不用递归。
代码如下,l用来保存增量计算出来的幂集,由于后续计算依赖于之前计算的结果,这里也没有用yield,直接返回一个list。因为这个计算过程中不会出现重复的子集,所以直接用list.extend()代替了取合集(union)的操作。同样,在递归算法中的F()函数的实现中有检查是否是重复元素的操作,而在这里其实是不必要的:
def power_set(s):
l = [set(),]
for e in s:
l.extend(F(set((e,)), l))
return l
3. s的幂集 = { subsets(s, k) | k=0, 1, 2, ..., n}
其中subsets(s,k)表示s所有模为k的子集,即 包含k个元素。这个关系是显而易见的。因此只要求出subsets(s,k),幂集也就很容易了。求subset(s,k)的代码我没有自己写,在这里 有一个实现,也是递归的,它利用了幂集与二项式系数之间的关系以及帕斯卡法则 (其实跟杨辉三角所描述的关系是一样的),显得很优美。代码如下,其中k_subsets(s,k)是别人实现的subsets(s,k)的函数。
def power_set(s):
for k in range(0, len(s)+1):
for k_set in k_subsets(s,k):
yield k_set
除此了上述方法外,陈硕老大也介绍了用stl的next_permutaion()来生成组合数(链接 ),进而求幂集。我觉得这个方法跟上述第三种方法有相似的地方,都是利用了组合与幂集之间的关系,不过生成组合的方法不一样。我相信还有更多的方法可以解决这个问题。
解决同一个问题可以有很多种方法,而看似简单的一个问题,真正要正确地解出来也不是那么容易。由于python本身提供了对set的支持,实现幂集也轻松了很多。不过set对象本身不能作为set的元素,这一点有待推敲,我对python也不是太熟悉。
python求幂集_求幂集的算法 - Sethylar的个人页面 - OSCHINA - 中文开源技术交流社区...相关推荐
- python倒排索引实现_倒排索引原理和实现 - uncle_LLD的个人空间 - OSCHINA - 中文开源技术交流社区...
关于倒排索引 搜索引擎通常检索的场景是:给定几个关键词,找出包含关键词的文档.怎么快速找到包含某个关键词的文档就成为搜索的关键.这里我们借助单词--文档矩阵模型,通过这个模型我们可以很方便知道某篇文档 ...
- java如何测试定时器_如何测试定时任务 - 邓竣的个人页面 - OSCHINA - 中文开源技术交流社区...
系统一般会有一些后台定时任务,假设我们使用quartz实现定时任务,那么有两个测试功能点: 定时任务逻辑是否正确 定时器cron表达式编写是否正确,触发时间点是否正确 定时任务逻辑测试 如果定时任务在 ...
- java实现近邻聚类算法,近邻传播聚类算法 - osc_t74tdxrl的个人空间 - OSCHINA - 中文开源技术交流社区...
近邻传播聚类算法 1.算法简介 AP(Affinity Propagation)通常被翻译为近邻传播算法或者仿射传播算法,是在2007年的Science杂志上提出的一种新的聚类算法.AP算法的基本思想 ...
- 人工鱼群算法python代码_人工鱼群算法python_鱼群算法 - Brillou的个人空间 - OSCHINA - 中文开源技术交流社区......
本算法是参照李晓磊博士的论文实现的,详细的算法原理可阅读<一种新型的智能优化方法_人工鱼群算法_李晓磊> 算法基于鱼群的生存行为:在一片水域中,鱼存在的数目最多的地方就是本水域中富含营养物 ...
- python 过采样 权重实现_不平衡数据集的处理 - osc_sqq5osi1的个人空间 - OSCHINA - 中文开源技术交流社区...
一.不平衡数据集的定义 所谓的不平衡数据集指的是数据集各个类别的样本量极不均衡.以二分类问题为例,假设正类的样本数量远大于负类的样本数量,通常情况下通常情况下把多数类样本的比例接近100:1这种情况下 ...
- java 投票算法_摩尔投票算法 - woshixin的个人空间 - OSCHINA - 中文开源技术交流社区...
摩尔投票算法(Moore majority vote algorithm) 这个在wiki的介绍在https://en.wikipedia.org/wiki/Boyer%E2%80%93Moore_m ...
- python 千位分隔符_玩转千位分隔符输出 - leejun2005的个人页面 - OSCHINA - 中文开源技术交流社区...
1.Python 1.1 format方法: 2.7版本以上直接用format设置千分位分隔符 Python 2.7 (r27:82500, Nov 23 2010, 18:07:12) [GCC 4 ...
- python编程代码执行漏洞_代码执行漏洞 - 安全先师的个人空间 - OSCHINA - 中文开源技术交流社区...
0x00 前言 最近发现的一个新站,不妨试试手. 0x01 基础信息 漏洞点:tp5 method 代码执行,payload如下 POST /?s=captcha_method=__construct ...
- python读写磁盘扇区数据有什么用_磁盘存放数据原理 - osc_v8xs2czi的个人空间 - OSCHINA - 中文开源技术交流社区...
磁盘结构作用数据原理 拓扑图 盘面(side) 模型: 1.磁盘圆形盘面,一个磁盘内含有多个盘面. 2.层叠关系,每个盘面之间不会贴着. 3.第一个盘的正面成为0面,反面为1面:第二个盘正面为2面,反 ...
- python编程题说句心里话_说句心里话 A - osc_6kxooi0n的个人空间 - OSCHINA - 中文开源技术交流社区...
说句心里话 A ...
最新文章
- DES对称加密(2)三重DES
- ssm整合之七 事务以及404页面处理
- 【编程题目】复杂链表的复制☆
- 13个mysql数据库的实用SQL小技巧
- mPaas 运维流程介绍
- SQL Server类型与C#类型对应关系
- Linux——批量查找替换方法(VIM和sed)
- centos8 配置 dns_如何在Ubuntu 18.04上设置DNS名称服务器 | linux资讯
- 为何要搞 10 年?方舟编译器专家首次回应
- [湖南集训] 谈笑风生
- eslint 快捷键设置_eslint的妙用和快捷修复
- B站排行榜(简陋版)
- Java如何处理参数中带特殊符号的请求?
- 小试ESP8266(一) 一只电阻, 几条语句, 摆脱深度睡眠反复重启的困扰
- 电脑按键坏掉之后的解决办法
- Java登录界面的实现(注册、登录、背景图片)
- c语言题查询答案,C语言习题级答案.docx
- php 网页合成图片,PHP怎么把网页内容原封不动的给生成图片
- 关于空间拓扑(lynn的自语)
- 物联网开发笔记(27)- 使用Micropython开发ESP32开发板之控制240x240的oled屏幕(ST7789芯片)
热门文章
- 基于HyperVID数据集训练自己的车型识别系统
- 使用FFmpeg工具进行推流、拉流、截图、变速、转换,及常见问题处理
- python scipy实例_python简单实现最大似然估计scipy库的使用详解
- 医院管理系统/医院药品管理系统
- webrtc系列3——对于stun和turn的理解
- python阈值分割_Python实现otsu阈值分割算法
- 松下PLC REXT总线伺服案例 本案例采用松下FPXH系列的总线型 PLC和松下总线伺服共8轴的系统
- iOS 开发经验 - 转载
- 互联网行业概括,让我们熟悉和了解未来的工作环境
- SAP B1打印报表实现本页合计和本单合计的方法