探討:n個元素中取出m個元素問題

問題

從包含n個元素的集合中取出m個元素,輸出全部的m元列表。 python

根據是否容許元素重複和是否排序,有如下四種狀況: 算法

*)不可重複,排序 app

*)可重複,排序 post

*)不可重複,不排序(即隨機) spa

*)可重複,不排序 .net


簡單算法:

爲了簡化問題,咱們從0~n-1中輸出全部的m元子集。(實際上進行index變換後,很容易獲得原題的解) code

算法大致能夠分爲兩種:遞歸和迭代。迭代算法實際上能夠當作是動態算法的一種。 排序

不管是遞歸仍是迭代,重要的是找到以下等式: 遞歸

S(i, j) = F[S(i-1, j-1), S(i-1, j), S(i, j-1)] element


代碼

#!/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

相關文章
相關標籤/搜索