探讨:n个元素中取出m个元素问题

问题

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

你可能感兴趣的:(python,list,set,select,dict)