在我的课堂上,我们讨论了递归创建子集的问题。尽管对链接功能的工作方式一无所知,但我在一定程度上理解了它:
def subsets(nums):
def helper(subset, i):
if i == len(nums):
res.append(subset[:])
else:
helper(subset, i+1)
subset.append(nums[i])
helper(subset, i+1)
subset.remove(nums[i])
res = []
helper([], 0)
return res
print(subsets(["a","b","c"]))
输出:
[[], ['c'], ['b'], ['b', 'c'], ['a'], ['a', 'c'], ['a', 'b'], ['a', 'b', 'c']]
答案 0 :(得分:0)
我想说的是了解函数运行方式的最佳方法是在执行过程中跟踪其变量:
def subsets(nums):
def helper(subset, i):
print( "| "*i + "*"*90)
print( "| "*i + "*{:^88}*".format("STARTING OF helper (i={})".format(i)))
print( "| "*i + "*{:^88}*".format('res= {}, subset = {}'.format( res,subset,len(nums))))
print( "| "*i + "*{:^88}*".format(' '))
if i == len(nums):
print( "| "*i + "*{:^88}*".format('APPENDING "{}" to res'.format( (subset[:]))))
res.append(subset[:])
else:
helper(subset, i+1)
print( "| "*i + "*{:^88}*".format('INTERMEDIATE STEP'.format( res)))
print( "| "*i + "*{:^88}*".format('APPENDING "{}" to subset'.format( nums[i])))
subset.append(nums[i])
helper(subset, i+1)
print( "| "*i + "*{:^88}*".format('INTERMEDIATE STEP'.format( res)))
print( "| "*i + "*{:^88}*".format('REMOVING "{}" from subset'.format( nums[i])))
subset.remove(nums[i])
print( "| "*i + "*{:^88}*".format('res={}'.format( res)))
print( "| "*i + "*{:^88}*".format('END OF helper (i={})'.format( i)))
print( "| "*i + "*"*90)
print( "| "*i + " "*90)
print( "| "*i + " "*90)
res = []
helper([], 0)
return res
print(subsets(["a","b","c"]))
将产生
******************************************************************************************
* STARTING OF helper (i=0) *
* res= [], subset = [] *
* *
| ******************************************************************************************
| * STARTING OF helper (i=1) *
| * res= [], subset = [] *
| * *
| | ******************************************************************************************
| | * STARTING OF helper (i=2) *
| | * res= [], subset = [] *
| | * *
| | | ******************************************************************************************
| | | * STARTING OF helper (i=3) *
| | | * res= [], subset = [] *
| | | * *
| | | * APPENDING "[]" to res *
| | | * res=[[]] *
| | | * END OF helper (i=3) *
| | | ******************************************************************************************
| | |
| | |
| | * INTERMEDIATE STEP *
| | * APPENDING "c" to subset *
| | | ******************************************************************************************
| | | * STARTING OF helper (i=3) *
| | | * res= [[]], subset = ['c'] *
| | | * *
| | | * APPENDING "['c']" to res *
| | | * res=[[], ['c']] *
| | | * END OF helper (i=3) *
| | | ******************************************************************************************
| | |
| | |
| | * INTERMEDIATE STEP *
| | * REMOVING "c" from subset *
| | * res=[[], ['c']] *
| | * END OF helper (i=2) *
| | ******************************************************************************************
| |
| |
| * INTERMEDIATE STEP *
| * APPENDING "b" to subset *
| | ******************************************************************************************
| | * STARTING OF helper (i=2) *
| | * res= [[], ['c']], subset = ['b'] *
| | * *
| | | ******************************************************************************************
| | | * STARTING OF helper (i=3) *
| | | * res= [[], ['c']], subset = ['b'] *
| | | * *
| | | * APPENDING "['b']" to res *
| | | * res=[[], ['c'], ['b']] *
| | | * END OF helper (i=3) *
| | | ******************************************************************************************
| | |
| | |
| | * INTERMEDIATE STEP *
| | * APPENDING "c" to subset *
| | | ******************************************************************************************
| | | * STARTING OF helper (i=3) *
| | | * res= [[], ['c'], ['b']], subset = ['b', 'c'] *
| | | * *
| | | * APPENDING "['b', 'c']" to res *
| | | * res=[[], ['c'], ['b'], ['b', 'c']] *
| | | * END OF helper (i=3) *
| | | ******************************************************************************************
| | |
| | |
| | * INTERMEDIATE STEP *
| | * REMOVING "c" from subset *
| | * res=[[], ['c'], ['b'], ['b', 'c']] *
| | * END OF helper (i=2) *
| | ******************************************************************************************
| |
| |
| * INTERMEDIATE STEP *
| * REMOVING "b" from subset *
| * res=[[], ['c'], ['b'], ['b', 'c']] *
| * END OF helper (i=1) *
| ******************************************************************************************
|
|
* INTERMEDIATE STEP *
* APPENDING "a" to subset *
| ******************************************************************************************
| * STARTING OF helper (i=1) *
| * res= [[], ['c'], ['b'], ['b', 'c']], subset = ['a'] *
| * *
| | ******************************************************************************************
| | * STARTING OF helper (i=2) *
| | * res= [[], ['c'], ['b'], ['b', 'c']], subset = ['a'] *
| | * *
| | | ******************************************************************************************
| | | * STARTING OF helper (i=3) *
| | | * res= [[], ['c'], ['b'], ['b', 'c']], subset = ['a'] *
| | | * *
| | | * APPENDING "['a']" to res *
| | | * res=[[], ['c'], ['b'], ['b', 'c'], ['a']] *
| | | * END OF helper (i=3) *
| | | ******************************************************************************************
| | |
| | |
| | * INTERMEDIATE STEP *
| | * APPENDING "c" to subset *
| | | ******************************************************************************************
| | | * STARTING OF helper (i=3) *
| | | * res= [[], ['c'], ['b'], ['b', 'c'], ['a']], subset = ['a', 'c'] *
| | | * *
| | | * APPENDING "['a', 'c']" to res *
| | | * res=[[], ['c'], ['b'], ['b', 'c'], ['a'], ['a', 'c']] *
| | | * END OF helper (i=3) *
| | | ******************************************************************************************
| | |
| | |
| | * INTERMEDIATE STEP *
| | * REMOVING "c" from subset *
| | * res=[[], ['c'], ['b'], ['b', 'c'], ['a'], ['a', 'c']] *
| | * END OF helper (i=2) *
| | ******************************************************************************************
| |
| |
| * INTERMEDIATE STEP *
| * APPENDING "b" to subset *
| | ******************************************************************************************
| | * STARTING OF helper (i=2) *
| | * res= [[], ['c'], ['b'], ['b', 'c'], ['a'], ['a', 'c']], subset = ['a', 'b'] *
| | * *
| | | ******************************************************************************************
| | | * STARTING OF helper (i=3) *
| | | * res= [[], ['c'], ['b'], ['b', 'c'], ['a'], ['a', 'c']], subset = ['a', 'b'] *
| | | * *
| | | * APPENDING "['a', 'b']" to res *
| | | * res=[[], ['c'], ['b'], ['b', 'c'], ['a'], ['a', 'c'], ['a', 'b']] *
| | | * END OF helper (i=3) *
| | | ******************************************************************************************
| | |
| | |
| | * INTERMEDIATE STEP *
| | * APPENDING "c" to subset *
| | | ******************************************************************************************
| | | * STARTING OF helper (i=3) *
| | | *res= [[], ['c'], ['b'], ['b', 'c'], ['a'], ['a', 'c'], ['a', 'b']], subset = ['a', 'b', 'c']*
| | | * *
| | | * APPENDING "['a', 'b', 'c']" to res *
| | | * res=[[], ['c'], ['b'], ['b', 'c'], ['a'], ['a', 'c'], ['a', 'b'], ['a', 'b', 'c']] *
| | | * END OF helper (i=3) *
| | | ******************************************************************************************
| | |
| | |
| | * INTERMEDIATE STEP *
| | * REMOVING "c" from subset *
| | * res=[[], ['c'], ['b'], ['b', 'c'], ['a'], ['a', 'c'], ['a', 'b'], ['a', 'b', 'c']] *
| | * END OF helper (i=2) *
| | ******************************************************************************************
| |
| |
| * INTERMEDIATE STEP *
| * REMOVING "b" from subset *
| * res=[[], ['c'], ['b'], ['b', 'c'], ['a'], ['a', 'c'], ['a', 'b'], ['a', 'b', 'c']] *
| * END OF helper (i=1) *
| ******************************************************************************************
|
|
* INTERMEDIATE STEP *
* REMOVING "a" from subset *
* res=[[], ['c'], ['b'], ['b', 'c'], ['a'], ['a', 'c'], ['a', 'b'], ['a', 'b', 'c']] *
* END OF helper (i=0) *
******************************************************************************************
[[], ['c'], ['b'], ['b', 'c'], ['a'], ['a', 'c'], ['a', 'b'], ['a', 'b', 'c']]
要获得更深入的说明,您将看到的帮助程序将从0级的空列表开始执行。
对于每个低于len(nums)的辅助函数级别,递归函数将分支为2个新的递归函数,该函数将保留子集不变或将nums的第i个元素添加到其中。
对于最后一个级别,将把子集添加到结果中,并可以通过一些ascii艺术图轻松地对其进行可视化
nums = ['a','b','c']
level: 0='a' 1='b' 2='c' 3=add_to_res
[] ---> [] -----> [] ---------> []
| | |__________> ['c']
| |
| |______> ['b'] ------> ['b']
| |__________> ['b','c']
|
|____> ['a'] --> ['a'] ------> ['a']
| |__________> ['a','c']
|
|____> ['a','b'] --> ['a','b']
|__________> ['a','b','c']
从面向数学的角度出发,您可以考虑从上一次迭代开始:
答案 1 :(得分:0)
我将只讨论两个函数的关系,而不是递归算法。
内部函数helper
是主例程,外部函数subsets
只是为内部函数设置了参数。让我们用更明确的变量名和稍作更改来重写此函数:
def subsets(elements):
result = []
def subsets_recursive(subset, index):
if index == len(elements):
result.append(subset[:])
else:
subsets_recursive(subset, index + 1)
subset.append(elements[index])
subsets_recursive(subset, index + 1)
del subset[-1]
subsets_recursive([], 0)
return result
print(subsets(['a', 'b', 'c']))
我用del subset[-1]
代替了subset.remove(nums[i])
,因为remove()
意味着要进行搜索,但是我们知道我们在subsets
列表的末尾添加了新元素,并且仍然存在需要删除它时。 (即效率。)
现在,让我们重新编写代码以消除外部函数:
def subsets_recursive(elements, subset=[], index=0): # dangerous default value
result = []
if index == len(elements):
result.append(subset[:])
else:
result.extend(subsets_recursive(elements, subset, index + 1))
subset.append(elements[index])
result.extend(subsets_recursive(elements, subset, index + 1))
del subset[-1]
return result
print(subsets_recursive(['a', 'b', 'c']))
尽管subset=[]
被认为是一个危险的默认值(是一个容器),但在这种情况下,由于放入subset
中的任何东西都被再次取出, if 一切正常完成,因此可以在下次通话时使用。虽然这是一个很大的 if 。
要摆脱 dangerous 的默认设置,并向例程的用户隐藏我们不希望设置的两个额外参数,我们将其包装在一个非递归例程中,该例程仅接受一个参数,并以所需方式在内部设置调用。这使我们回到了开始的地方,但是这次实现了我可能做的方式:
def subsets(elements):
def subsets_recursive(subset, index):
result = []
if index == len(elements):
result.append(subset[:])
else:
result.extend(subsets_recursive(subset, index + 1))
subset.append(elements[index])
result.extend(subsets_recursive(subset, index + 1))
del subset[-1]
return result
return subsets_recursive([], 0)
print(subsets(['a', 'b', 'c']))
相对于副作用,我更喜欢适当的return
通话。