我在百度,触宝面试的时候,他们都问到了递归。
递归是一个很有意思的问题,其中的经典问题有汉诺塔,fibonacci 数列问题。汉诺塔是比较难的问题,fibonacci 是比较简单的问题。
触宝面试的时候,面试官问我如何对一个数组进行全排列。全排列的意思是,给定一个数组[1,2,3],列出它所有可能的排列方式:[1,2,3],[1,3,2],[2,3,1],[2,1,3],[3,1,2],[3,2,1]共6种。面试官就提示我可以用递归来做。
我们看一下人脑思维针对全排列所给出的排列方式:
数组为[1,2,3]时,步骤如下:
1放第一位,然后全排列数组[2,3],得到[1,2,3],[1,3,2]
2放第一位,然后全排列数组[1,3],得到[2,1,3],[2,3,1]
3放第一位,然后全排列数组[1,2],得到[3,1,2],[3,2,1]
数组为[1,2]时,排列有两种:[1,2],[2,1]。排列步骤如下:
1放第一位,然后全排列数组[2],得到[1,2]
2放第一位,然后全排列数组[1],得到[2,1]
数组为[1]时, 排列方式只有一种:[1]
可以看到当前问题都会基于上一个小问题的解决。这就可以用到递归的方法。
全排列的递归代码如下:
COUNT=0
def perm(n,begin,end):
global COUNT
if begin>=end:
print n
COUNT +=1
else:
i=begin
for num in range(begin,end):#依次进行换位
n[num],n[i]=n[i],n[num]
perm(n,begin+1,end)
n[num],n[i]=n[i],n[num]#对于上一个递归来说,置换回来的,还要置换回去
n=[1,2,3,4]
perm(n,0,len(n))
print COUNT
求了全排列之后,我们用递归的方法求一下全组合。
全组合也可以看作是求一个集合的所有子集。
例子,{1,2,3}的所有子集就是{1},{2},{3},{1,2},{1,3},{2,3},{1,2,3}以及空集合{}。
组合排列,排列组合。
def PowerSetsRecursive(items):
"""Use recursive call to return all subsets of items, include empty set"""
if len(items) == 0:
#if the list is empty, return the empty list
return [[]]
subsets = []
first_elt = items[0] #first element
rest_list = items[1:]
#Strategy:Get all subsets of rest_list; for each of those subsets, a full subset list
#will contain both the original subset as well as a version of the sebset that contains the first_elt
for partial_sebset in PowerSetsRecursive(rest_list):
subsets.append(partial_sebset)
next_subset = partial_sebset[:] +[first_elt]
subsets.append(next_subset)
return subsets
items = [1,2,3,4]
print PowerSetsRecursive(items)
运行结果:
[[], [1], [2], [2, 1], [3], [3, 1], [3, 2], [3, 2, 1], [4], [4, 1], [4, 2], [4, 2, 1], [4, 3], [4, 3, 1], [4, 3, 2], [4, 3, 2, 1]]