python解決組合問題


1.問題描述

 比如9個數中取4個數的組合以及列出各種組合,該如何做?

 我們可以考慮以下一個簡單組合:從1,2,3,4,5,6中,如何選取任意四個數的組合。

 固定:1   2  3  ,組合有1234 1235 1236 

 固定1 2 4,組合有:1245 1246

 固定1 2 5,組合有:1256

    固定1 3 4,組合有:1345 1346

 固定1 3 5,組合有:1356

 固定1 4 5,組合有:1456

 固定2 3 4,組合有:2345 2346

 固定2 3 5,組合有:2356

 固定2 4 5,組合有:2456

 固定3 4 5,組合有:3456

  共有15種組合

2.簡單實現一下組合算法

  首先,我們分析上面列出的10個步驟,對於1),很明顯,在固定了1 2 3這三個數之后,第四個數就是4、5、6三個數進行了循環(還記得循環嗎,計算機最拿手的就是做循環)。其次,我們再分析1)2)3)這三個步驟中固定的數字,前兩個沒有變,都是1 2,只是第三個數在進行循環(又是循環)。

  通過分析,我們可以找到這樣的規律:

    1    先固定3個數,讓第四個數進行循環

    2    讓第三個數循環,重復第一步

    3    讓第二個數循環,重復第一步

    4    讓第一個數循環,重復第一步

def combNumberLoop4(m, b):
    totalNumber = 0
    for i in range(1, m+2-4):
        b[0] = i
        for j in range(i+1, m+2-3):
            b[1] = j
            for k in range(j+1, m+2-2):
                b[2] = k
                for l in range(k+1, m+2-1):
                    b[3] = l
                    print b
                    totalNumber += 1
    return totalNumber

 
group=[99,99,99,99]
print "\nUsing Loop: %d\n" % combNumberLoop4(6, group)

  程序的輸出結果,正如之前分析的那樣。

3.如何遞歸解決組合問題

  我們再回到C(6,4)問題,除了上面列出的十個步驟,我們換個思路:

    如果在6個數中選定一個數,那么確定剩下的3個數是不是變為了“從5個數中選3個數的組合問題”了呢?以此類推,這似乎變成了一個“遞歸”問題了,確實,我們可以用遞歸的思路來解決這個問題。

    對於C(m, n)列出所有組合的問題,可以按照一下的步驟來進行編程,這次我們按從后往前的順序來列出所有組合:

      1   選定一個元素i,在范圍[m, n]內進行循環

      2   將i 作為所求組合的最后一個元素

      3   如果n-1>0,進行遞歸調用,求C(m-1, n-1);否則,輸出結果

      4   重復①

    注意,設計遞歸函數一定要有終止條件,否則會造成“死循環”。

實現的代碼如下:

def combNumber(m, n, b):
    global totalNumberR
    for i in range(m, n-1, -1):   
        b[n-1] = i
        if n-1>0:
            combNumber(i-1,n-1,b)
        else:
            print b
            totalNumberR += 1
    return totalNumberR

 

group=[99,99,99,99,99]
totalNumberR = 0
print "\nUsing Recursive: %d\n" % combNumber(7,5,group) 

  遞歸的使用,讓程序寫起來非常的簡潔,但是,在寫程序的時候,我有兩個地方(其實程序也就難在這兩個地方),折騰了好幾天才弄清楚:

     首先是for循環的循環范圍如何確定;

     其次是遞歸調用時使用的參數設計;

3.python提供的內置組合函數

def combinations_with_replacement(iterable, r):
    # combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC
    pool = tuple(iterable)
    n = len(pool)
    if not n and r:
        return
    indices = [0] * r
    yield tuple(pool[i] for i in indices)
    while True:
        for i in reversed(range(r)):
            if indices[i] != n - 1:
                break
        else:
            return
        indices[i:] = [indices[i] + 1] * (r - i)
        yield tuple(pool[i] for i in indices)

4.更多組合算法

  請點擊我:https://docs.python.org/3/library/itertools.html?highlight=combinations#itertools.combinations

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM