问题:
从包含n个元素的集合中取出m个元素,输出所有的m元列表。
根据是否允许元素重复和是否排序,有以下四种情况:
*)不可重复,排序
*)可重复,排序
*)不可重复,不排序(即随机)
*)可重复,不排序
简单算法:
为了简化问题,我们从0~n-1中输出所有的m元子集。(实际上进行index变换后,很容易得到原题的解)
算法大体可以分为两种:递归和迭代。迭代算法实际上可以看成是动态算法的一种。
无论是递归还是迭代,重要的是找到如下等式:
S(i, j) = F[S(i-1, j-1), S(i-1, j), S(i, j-1)]
代码
#!/usr/bin/env python
import sys
def getAllSubsets(n, m):
'''
get all m-element subset from 0~n-1
no duplicates, sorted
'''
# pre: 0<=m<=n
# post: all subsets got
if m<0 or m>n:
print 'invalid args, prog exit'
sys.exit(1)
if m==0:
return [[]]
if m==n:
return [[i for i in range(0, n)]]
subset1 = getAllSubsets(n-1, m)
subset2 = getAllSubsets(n-1, m-1)
for L in subset2:
L.append(n-1)
return subset2+subset1
def getAllSubsets2(n, m):
'''
get m-element subset from 0~n-1
allow duplicates, sorted
'''
# pre: 0<=m
# post: all subsets got
if m<0:
print 'invalid args, prog exit'
sys.exit(1)
if m==0:
return [[]]
if n==1:
return [[0 for i in range(0, m)]]
subset1 = getAllSubsets2(n-1, m)
subset2 = getAllSubsets2(n, m-1)
for L in subset2:
L.append(n-1)
return subset2+subset1
def getAllSubsets3(n, m):
'''
get m-ele subset from 0~n-1
no duplicates, unsorted
'''
# pre: 0<=m<=n
if m<0 or m>n:
print 'invalid args, prog exit'
sys.exit(1)
if m==0:
return [[]]
elif m<=n:
subset = getAllSubsets3(n, m-1)
subset_ret = []
for i in range(0, n):
for s in subset:
if i not in s:
s_tmp = s[:]
s_tmp.append(i)
subset_ret.append(s_tmp)
return subset_ret
def getAllSubsets4(n, m):
'''
get m-ele subset from 0~n-1
allow duplicates, unsorted
'''
# pre: 0<=m
if m<0 or n<1:
print 'invalid args, prog exit'
sys.exit(1)
if m==0:
return [[]]
else:
subset = getAllSubsets4(n, m-1)
subset_ret = []
for i in range(0, n):
for s in subset:
s_tmp = s[:]
s_tmp.append(i)
subset_ret.append(s_tmp)
return subset_ret
def getSubs(n, m, flag=1):
print 'n=%s, m=%s' % (n,m)
if flag==1: # no duplicates, sorted
LL = getAllSubsets(n, m)
elif flag==2: # allow duplicates, sorted
LL = getAllSubsets2(n, m)
elif flag==3: # no duplicates, unsorted
LL = getAllSubsets3(n, m)
elif flag==4: # allow duplicates, unsorted
LL = getAllSubsets4(n, m)
for L in LL:
print L, '\t',
print
print len(LL)
return
if __name__ == '__main__':
getSubs(4, 2, int(sys.argv[1]))
简单结果示例
chenqi@chenqi-laptop ~/MyPro/Algorithms/set-operations $ ./get_all_subsets.py 1
n=4, m=2
[2, 3] [1, 3] [0, 3] [1, 2] [0, 2] [0, 1]
6
chenqi@chenqi-laptop ~/MyPro/Algorithms/set-operations $ ./get_all_subsets.py 2
n=4, m=2
[3, 3] [2, 3] [1, 3] [0, 3] [2, 2] [1, 2] [0, 2] [1, 1] [0, 1] [0, 0]
10
chenqi@chenqi-laptop ~/MyPro/Algorithms/set-operations $ ./get_all_subsets.py 3
n=4, m=2
[1, 0] [2, 0] [3, 0] [0, 1] [2, 1] [3, 1] [0, 2] [1, 2] [3, 2] [0, 3] [1, 3] [2, 3]
12
chenqi@chenqi-laptop ~/MyPro/Algorithms/set-operations $ ./get_all_subsets.py 4
n=4, m=2
[0, 0] [1, 0] [2, 0] [3, 0] [0, 1] [1, 1] [2, 1] [3, 1] [0, 2] [1, 2] [2, 2] [3, 2] [0, 3] [1, 3] [2, 3] [3, \
3]
16
参考链接:http://www.oschina.net/question/817257_76793