从包含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