两种求幂集的方法

今天这一题是求幂集。小学数学都忘得差不多了… 幂集是什么?

幂集(power set)是一个集合的所有子集。比如[1, 2, 3]的幂集就是:

[[], [1], [2], [1, 2], [3], [1, 3], [2, 3], [1, 2, 3]]

不过这道题有一个额外的要求:

在求幂集时要以“深度优先搜索”(depth-first search)的形式进行。也就是说,对于集合的每个元素,都有“取”和“舍”两种选择;在深度优先时,我们优先选择“舍”。仍以[1, 2, 3]为例,在这种情况下,它的幂集应该是:

[[], [3], [2], [2, 3], [1], [1, 3], [1, 2], [1, 2, 3]]

现在给定一个列表,如何以深度优先遍历的方法找出它的幂集?

这道题有两种思路。第一种,是采用回溯法。用白话说,就是在每一个分叉路口,偏执的选择一条道走到黑,此时再返回至上一个路口选择另外一条道继续… 这个过程相当于下面这个二叉树:

用递归实现非常简单:用对应输入集合列表的另一个列表res保存当前这条路上每个元素是取还是舍,然后继续往前走直到列表末尾,最后输出这条路上所有是“取”的元素。实现时为简单起见使用了嵌套函数。

def powerset(nums):
    powerset = []
    res = [0] * len(nums)

    def visit(i):
        if i == len(nums):
            powerset.append([num for j, num in enumerate(nums) if res[j] == 1]) # 输出这条路上所有是“取”的元素
        else:
            res[i] = 0
            visit(i+1) # 先“舍”,继续往前走
            res[i] = 1
            visit(i+1) # 再“取”,继续往前走

    visit(0)

    return powerset

另外一种思路是观察:

[1, 2, 3] -> [[], [3], [2], [2, 3], [1], [1, 3], [1, 2], [1, 2, 3]]

幂集是不是相当于[1, 2, 3]按照[0, 0, 0], [0, 0, 1], … [1, 1, 1]选择出来的?而[0, 0, 0], [0, 0, 1], … [1, 1, 1]既可以看成0-7的二进制表达,也可以看作是3个(0, 1)的笛卡尔积。

实现要点:

1. 对一个集合按照selector进行选择:

用itertools的compress方法。

2. 将十进制数转换为前面补0的固定长度的二进制数:

用format函数。

3. 求多个集合的笛卡尔积:

用itertools的product方法。

借用某个最优解法如下:

from itertools import product, compress

def powerset(nums):
    return [list(compress(nums, pattern)) for pattern in product((0, 1), repeat=len(nums))]

其实,如果没有深度优先的要求,求一个集合的幂集是非常简单的,用itertools模块的combinations方法就可以轻松做到:

from itertools import combinations

def power(s):
    return [list(c) for i in range(len(s)+1) for c in combinations(s, i)]

解决一个问题的方法多多,最重要是善于观察和总结,对吗?

时间: 2024-10-18 15:00:39

两种求幂集的方法的相关文章

数据归一化和两种常用的归一化方法

数据标准化(归一化)处理是数据挖掘的一项基础工作,不同评价指标往往具有不同的量纲和量纲单位,这样的情况会影响到数据分析的结果,为了消除指标之间的量纲影响,需要进行数据标准化处理,以解决数据指标之间的可比性.原始数据经过数据标准化处理后,各指标处于同一数量级,适合进行综合对比评价.以下是两种常用的归一化方法: 一.min-max标准化(Min-Max Normalization) 也称为离差标准化,是对原始数据的线性变换,使结果值映射到[0 - 1]之间.转换函数如下: 其中max为样本数据的最大

找1~100之间素数的两种比较简单的方法

方法一:利用一个布尔类型的值的判断,优点想法更直接易懂 public static void main(String[] args) { for(int i=2;i<=100;i++){ boolean b=true; for(int n=2;n<i;n++){ if(i%n==0){ b=false; break; } } if(b==true){ System.out.print(i+"\t"); } } } 方法二:能被2和这个数本身以外的数整除的都不是素数.理解难但

【转】数据归一化和两种常用的归一化方法

转自http://www.cnblogs.com/chaosimple/p/3227271.html 数据标准化(归一化)处理是数据挖掘的一项基础工作,不同评价指标往往具有不同的量纲和量纲单位,这样的情况会影响到数据分析的结果,为了消除指标之间的量纲影响,需要进行数据标准化处理,以解决数据指标之间的可比性.原始数据经过数据标准化处理后,各指标处于同一数量级,适合进行综合对比评价.以下是两种常用的归一化方法: 一.min-max标准化(Min-Max Normalization) 也称为离差标准化

[转] 数据归一化和两种常用的归一化方法

原文链接:http://www.cnblogs.com/chaosimple/p/3227271.html 数据标准化(归一化)处理是数据挖掘的一项基础工作,不同评价指标往往具有不同的量纲和量纲单位,这样的情况会影响到数据分析的结果,为了消除指标之间的量纲影响,需要进行数据标准化处理,以解决数据指标之间的可比性.原始数据经过数据标准化处理后,各指标处于同一数量级,适合进行综合对比评价.以下是两种常用的归一化方法: 一.min-max标准化(Min-Max Normalization) 也称为离差

两种 设置 背景图片方法

两种设置背景图片方法 //    UIView *navigationbarTitleTupian =[[UIView alloc]initWithFrame:CGRectMake(0, 0, 40, 30)]; //    UIImageView *imageTitleTupian =[[UIImageView alloc]initWithImage:[UIImage imageNamed:@"bg.png"]]; // //    [navigationbarTitleTupian

ExtJS学习-------Ext.define的别名和备用名,两种定义静态方法的方法,混入属性和其他属性

(1)Ext.define起别名和备用名 Ext.onReady(function(){ Ext.define('User',{ config:{ name:'张三', age:23 }, //使用别名 alias:'alias_user', //使用备用名 alternateClassName:'alternateClassName_user', constructor:function(config){//构造器 var me=this; me.initConfig(config); } }

Eclipse中SVN的安装步骤(两种)和使用方法

一.给Eclipse安装SVN,最常见的有两种方式:手动方式和使用安装向导方式.具体步骤如下: 方式一:手动安装 1.从官网下载site-1.6.9.zip文件,网址是:subclipse.tigris.org 2.从中解压出features与plugins文件夹,复制到E:/MyEclipse/myPlugin/svn里面,其它的*.xml文件不要. 3.在E:/MyEclipse/MyEclipse X.X/dropins下新建文件svn.link,内容是:path=E://MyEclips

两种解析JSON的方法

对一段json字符串,解析有两种方法 第一种是普通的解析方法:如下 比较有代表性的解析json的方法,嘿嘿 还有一种是利用Gson解析,这种方法解析起来比较方便,不需要像那种普通的方法一样写那么多代码 注:在使用gson的时候类中的属性名称要和json中的属性名称一样 两种解析JSON的方法

统计学习基础(第二版)两种简单的预测方法:最小二乘和最近邻

2.3两种简单的预测方法:最小二乘和最近邻 在本节中我们详细讨论两种简单但有效的预测方法,使用最小二乘线性模型拟合和k最近邻预测.线性模型对结构做了大量的假设,但是可能会产生不准确的预测.K-最近邻对结构做了适当的假设,所以预测通常是精确但不稳定的. 2.3.1线性模型和最小二乘 在过去的30年中,线性模型一直是统计学的支柱,而且现在依然是我们最重要的工具之一.给定一个输入向量,通过以下模型来预测Y: 其中是截距,在机器学习中又叫做偏置,通常在X中包含一个常数变量1,在系数向量中包含是方便的.这