问题描述:
给定一个包含n个元素的列表,从中选择m个元素作为一个子列表,求解所有可能的子列表。
例如:
一个列表是[1,2,3,4],从中任选3个数作为一个子列表。
则所有可能的子列表为:[1,2,3], [1,2,4], [1,3,4], [2,3,4]。共有
种。
用python语言描述就是:
def getSubLists(lis=[],m=0):
allAns=[]
# type your code here
return allAns
| 输入: [1,2,3,4]
| 输出:[[1,2,3], [1,2,4], [1,3,4], [2,3,4]]
问题分析:
从数学角度来看,从n个数字中任取m个,所有可能的取法总数量为:
。用Python求这个数量结果是很简单的,但是要实际输出所有组合时,却不是易事(对我自己而言)。
就我自己的经验而言,例如从[a,b,c,d,e]中任选3个,我一般会采用如下搜索方式手动去找出所有组合:
这种方法反映了一种递归思想:
选定了原列表种第
个数作为子列表第一个数,接下来就是把原列表第
数作为子列表第二个数,最后从原列表第
个数后面的所有数中任选一个作为子列表第三个数。
也就是说,一旦确定了“谁”作为子列表第一个数,那么接下来采用的方法都是一样的,这不就是递归嘛!
编程实现:
若要采用递归方式,那问题描述中的函数getSubLists不能直接调用自己,因为每次自我调用后,存储结果的allAns会被刷新,所以可以定义辅助函数subLists专门用来做递归:
def getSubLists(lis=[],m=0):
allAns = [] #用来存储所有递归中的子列表
ans = [None for i in range(m)] #预先填充m个None,用来存储每次递归中的子列表
subLists(lis,m,ans,allAns)
return allAns
def subLists(lis=[],m=0,ans=[],allAns=[]):
# recursive function codes
if m==0:
# m==0是某次递归返回的条件之一:子列表的第三个数已经选出。
# 意味着已到达某个方向的最大递归深度
print('allAns is ',allAns,'before append ans:',ans)
allAns.append(ans.copy())
#这里有意思了,如果不用copy,那么ans即使已经存储在allAns,也会被其它递归方向中的ans刷新
print('allAns is ', allAns, 'after append ans:', ans)
return
if len(lis)
# 递归函数直接返回的条件之一:从4个数里面选5个数出来是不可能的。
print("short list!")
return
length=len(lis)
for iter in range(length-m+1): #可以作为子列表一员的数在lis中的index
ans[-m]=lis[iter] #lis[iter]作为子列表倒数第m个数
if iter+1
subLists(lis[iter+1:],m-1,ans,allAns)
else:
print('allAns is ', allAns, 'before append ans:', ans)
allAns.append(ans.copy())
print('allAns is ', allAns, 'after append ans:', ans)
return
好了,是不是挺简单的,来试一下效果:
if __name__=='__main__':
liss=[1,2,3,4]
m=3
print('The answer for choosing any 3 Numbers from the list:',getSubLists(liss,m))
Outputs:
allAns is [] before append ans: [1, 2, 3]
allAns is [[1, 2, 3]] after append ans: [1, 2, 3]
allAns is [[1, 2, 3]] before append ans: [1, 2, 4]
allAns is [[1, 2, 3], [1, 2, 4]] after append ans: [1, 2, 4]
allAns is [[1, 2, 3], [1, 2, 4]] before append ans: [1, 3, 4]
allAns is [[1, 2, 3], [1, 2, 4], [1, 3, 4]] after append ans: [1, 3, 4]
allAns is [[1, 2, 3], [1, 2, 4], [1, 3, 4]] before append ans: [2, 3, 4]
allAns is [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]] after append ans: [2, 3, 4]
The answer for choosing any 3 Numbers from the list: [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]
Bingo! 欢迎指教