递归 求全排列与全组合

我在百度,触宝面试的时候,他们都问到了递归。

递归是一个很有意思的问题,其中的经典问题有汉诺塔,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]]

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值