这必须是一个经典的面试问题,然而,我在理解它时遇到了问题。
下面是我在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
param(http://www.geeksforgeeks.org/print-all-possible-combinations-of-r-elements-in-a-given-array-of-size-n/)但是
我的问题是我的实施有什么问题?
你能说清楚吗?
要进行调试,我打印出来"使用"每次。打印后,used
参数变为(真,真,真,真)" ad"那么它并没有比这更深入。如果我坚持使用used
,那么解决used
的明智方法是什么?
答案 0 :(得分:3)
当您回溯时,您忘记取消设置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])
在您当前的实施中,您从选择 used[i]
作为值时,将True
设置为i
。如果稍后您决定选择另一个分支,则应正确进行簿记,从而取消设置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
答案 1 :(得分:2)
派对迟到了,但我认为你应该更多地利用递归。没有必要传递任何多余的论据。
这是一种更简单的方法:
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
字符组合。
对于size-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']