繁体   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