算法—— 集合的子集
Posted bopo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法—— 集合的子集相关的知识,希望对你有一定的参考价值。
问题
给定一个集合,输出它的所有子集。
示例:
给定集合{1,2,3},应该输出:
{}
{1}
{2}
{1, 2}
{3}
{1, 3}
{2, 3}
{1, 2, 3}
解法1:增量构造法
增量构造法,每次选择一个元素放到集合中,每次操作的结果即是一个子集。
递归操作,每次向当前集合中添加一个比当前集合中最大的元素大1的数。
from __future__ import print_function def print_subset(n, lst, cur): for i in range(cur): print(lst[i]+1, end=‘‘) print() if cur: s = lst[cur - 1] + 1 else: s = 0 for i in range(s, n): lst[cur] = i print_subset1(n, lst, cur+1)
解法2:位向量法
构造位向量(可理解为构造一个数组),该向量中的每一位置可以取0值或者1值,0和1分别代表该位置上对应的值是否在集合中。如向量为[1, 0, 0, 1],其第1和4位上有1,所以该向量表示的集合为{1, 4}。
思路:
如果需要用向量来表示集合,那么需要保证向量的每一种变化能够刚好覆盖集合的每一种可能性。
对n求子集,构造长度为n的向量,每一位可以代表取或者不取该位置的值,共有2^n中可能。
from __future__ import print_function def print_subset(n, lst, cur): if cur == n: for i in range(n): if lst[i]: print(i+1, end=‘‘) print() else: lst[cur] = 0 print_subset(n, lst, cur+1) lst[cur] = 1 print_subset(n, lst, cur+1)
解法3:二进制法
我们可以使用二进制法来表示子集。对于n求子集,其子集有2^n个(包括空集),比如n = 4,其有16个子集,这16个子集用二进制可以表示成:
0->0000->{} 1->0001->{1} 2->0010->{2} 3->0011->{1,2} 4->0100->{3} 5->0101->{1,3} ... 15->1111->{1,2,3,4}
思路:
求n的子集,可以依次处理1到2^n - 1之间的每一个数,每个数取出它二进制表示中的1的位置,以此表示该数对应的集合。比如5,二进制表示的后四位为0101,其在第1和第3位处有1,那么,其代表的集合为{1, 3}。使用位运算中与(&)操作,可以方便的求出二进制某位置上是否为1。
from __future__ import print_function s = 1 n = 4 while s < (1 << n): # 依次遍历1到2^n - 1之间的每一个数 for i in range(n): # 每一个数使用&操作判断该位置上是否有1,有打印或者保存起来 if s & (1 << i): print(i+1, end=‘‘) print() s += 1
以上是关于算法—— 集合的子集的主要内容,如果未能解决你的问题,请参考以下文章