簡體   English   中英

打印n選擇使用遞歸的k組合算法

[英]Print n choose k combination algorithm using recursion

這一定是一個經典的面試問題,但是,我在理解它時遇到了問題。

下面是我在Python中的實現,如果您運行它,它只會打印ab, ac, ad 它不會達到'b' (bc, bd)級別。

def Print_nCk (the_list, k, str_builder, used):
    if len(str_builder) == k:
        print str_builder
        return 
    else:
        for i in xrange(len(the_list)):
            if used[i] !=True:
                str_builder+=the_list[i]
                used[i] = True
                Print_nCk(the_list, k, str_builder, used)
                str_builder = str_builder[:-1]


Print_nCk(['a','b','c','d'], 2, "",[False,False,False,False])

當以上行通過時,正確的答案是ab,ac,ad,bc,bd,cd

我從這里知道正確的實施方式,而不使用used參數( http://www.geeksforgeeks.org/print-all-possible-combinations-of-r-elements-in-a-given-array-of-size-n/ ),但我的問題是我的實現有什么問題?

你能闡明一點嗎?

為了調試,我每次都打印出“二手”。 打印“ ad”后,已used參數變為(True,True,True,True),然后沒有比這更深的了。 如果我堅持使用used貨,修復used貨的明智方法是什么?

回溯時,您忘記取消設置used[i]

def Print_nCk (the_list, k, str_builder, used):
    if len(str_builder) == k:
        print str_builder
        return
    else:
        for i in xrange(len(the_list)):
            if used[i] != True:
                str_builder += the_list[i]
                used[i] = True
                Print_nCk(the_list, k, str_builder, used)
                str_builder = str_builder[:-1]
                used[i] = False


Print_nCk(['a','b','c','d'], 2, "",[False,False,False,False])

在當前的實現中,從選擇 i作為值的那一刻起,您就將used[i]設置為True 但是,如果稍后您決定選擇另一個分支,則應正確進行簿記,從而取消設置used[i]

請注意,現在將生成"ab""ba" 因此,您將生成具有對稱性的組合 如果不希望這樣,可以使用附加參數 這樣可以確保您使用的索引不低於先前選擇的索引

def Print_nCk (the_list, k, str_builder, used, prev = 0):
    if len(str_builder) == k:
        print str_builder
        return
    else:
        for i in xrange(prev,len(the_list)):
            if used[i] != True:
                str_builder += the_list[i]
                used[i] = True
                Print_nCk(the_list, k, str_builder, used, i+1)
                str_builder = str_builder[:-1]
                used[i] = False


Print_nCk(['a','b','c','d'], 2, "",[False,False,False,False])

然而,這或多或少地破壞了使用“二手”陣列的目的。 您可以簡單地使用prev

def Print_nCk (the_list, k, str_builder, prev = 0):
    if len(str_builder) == k:
        print str_builder
        return
    else:
        for i in xrange(prev,len(the_list)):
            str_builder += the_list[i]
            Print_nCk(the_list, k, str_builder, i+1)
            str_builder = str_builder[:-1]


Print_nCk(['a','b','c','d'], 2, "")

然后打印:

>>> Print_nCk(['a','b','c','d'], 2, "")
ab
ac
ad
bc
bd
cd

參加聚會有點晚,但是我認為您應該更多地利用遞歸。 無需傳遞任何多余的參數。

這是一個更簡單的方法:

def Print_nCk(the_list, size):
    combs = []
    if size == 1: # the base case
        return the_list

    for i, c in enumerate(the_list[:-size + 1]):
        for sub_comb in Print_nCk(the_list[i + 1:], size  - 1): # generate and return all sub-combos of size - 1
            combs.append(c + sub_comb) # for each sub-combo, add the sizeth (or n - sizeth) character

    return combs

此方法生成size - 1組合,並將它們與size th的字符組合在一起。

對於2號組合:

>>> Print_nCk(['a','b','c','d'], 2)
['ab', 'ac', 'ad', 'bc', 'bd', 'cd']

對於3號組合:

>>> Print_nCk(['a','b','c','d'], 3)
['abc', 'abd', 'acd', 'bcd']

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM