python实现子集和问题

  1. 问题:一个序列,找出其中子集,这里为了简单,假设子集和等于0,如果序列长n,那么显然知道子集总数为pow(2,n)个。怎么找符合子集和为0的那些子集呢?
  2. 算法思路一:暴力破解法,循环找所有子集,查找满足条件的子集并输出
  3. 用到一些基本的函数:zip,可以理解为压缩方法,比如
lst
[-7, -3, -2, 5, 8]
m
'00001'
temp = zip(lst, m)
temp
[(-7, '0'), (-3, '0'), (-2, '0'), (5, '0'), (8, '1')]

压缩起来了,清晰不?
解压缩咋办?直接zip(*temp),这里的星号就是完成解压缩功能的

zip(*temp)
[(-7, -3, -2, 5, 8), ('0', '0', '0', '0', '1')]
  1. 还有个好玩的函数,filter, 过滤掉不符合条件的元素,返回由符合条件的元素组成的新列表
zip(lst, m)
[(-7, '0'), (-3, '0'), (-2, '0'), (5, '0'), (8, '1')]
lambda x: x[1] != ‘0’
 at 0x0000000003F1A908>
temp = filter(lambda x: x[1]!='0',  zip(lst, m))
temp
[(8, '1')]

这里应该能明白filter功能了吧?对列表[(-7, ‘0’), (-3, ‘0’), (-2, ‘0’), (5, ‘0’), (8, ‘1’)]中的元素判断,过滤掉每个列表中元素如(-7,‘0’)这样式的元素,也就是lambda函数中的x, 找这些元素的第1个值,索引从0开始,所以要看看x[1]也就是(-7,‘0’)后面的这个第1个元素’0’,等于0的过滤掉,留下不等于‘0’的组成新的列表,所以结果等于[(8,‘1’)]

  1. 接着来,如果外面套上map函数呢?map根据提供的函数对指定序列做映射,这里函数的功能是找第0个元素
filter(lambda x: x[1]!='0',  zip(lst, m))
[(8, '1')]
map(lambda x: x[0],  filter(lambda x: x[1]!='0',  zip(lst, m)))
[8]
  1. 上面用到的labmda函数,是匿名函数,和普通函数类似,只是函数匿名了,为了方便写,但是不利于理解哈。
  2. 这里还有个更好玩的函数,字符串下面有个zfill函数:返回指定长度的字符串,原字符串右对齐,前面填充0.
m
'00001'
len(lst)
5
m.zfill(5)
'00001'

这个东东常用在对数字啊,序列啊,DNA,基因啥的进行编码的时候使用,将其转换为二进制编码
12. 接下来就到yield关键字了,这个在python中是生成器,用于生成可随时挂起随时调用的函数,类似于return,但是功能更强大,可以节省内存使用率。
13. 接下来的暴力破解就有意思了,不多说了,基础搞定,直接看算法,你的思路就完整建立了:

def subset_sum(lst, target):
    for i in range(1, 2**len(lst)):
        pick = list(mask(lst, bin(i)[2:]))
        if sum(pick) == target:
            yield pick
def mask(lst, m):
    m = m.zfill(len(lst))
    return map(lambda x: x[0],  filter(lambda x: x[1]!='0',  zip(lst, m)))

lst = [-7, -3, -2, 5, 8]
target = 0
k = subset_sum(lst, target)
print(list(k))

你可能感兴趣的:(作业题)