python:递归案例之阶乘,幂,二分查找

一、递归之阶乘

假设你要计算数字n的阶乘。n的阶乘为n×(n-1)×(n-2)×┈×1,在数学领域的用途非常广泛。例如,计算将n个人排成一队有多少中方式。如何计算阶乘呢?可使用循环。

def factorial(n):
    result = n
    for i in range(1, n):
        result *= i
    result result

这种实现可行,而且直接了当。大致而言,它是这样的:首先将result。但如果你愿意,可采取不同的做法。关键在于阶乘的数学定义,可表述如下。

(1).1的阶乘的1。

(2).对于大于1的数字n,其阶乘为n-1的阶乘以n

如你所见,这个定义与本文开头的定义完全等价。

下面来考虑如何使用函数来实现这个定义。

def factorial(n):
    if n == 1:
        return 1
    else:
        return n * factorial(n - 1)

这是前述定义的直接实现。

二、递归之幂

假设假药计算幂,就像内置函数pow和运算符**所做的那样。要定义一个数字的整数次幂 ,有多种方式,先看一个简单的定义:power(x, n)(x的n次幂)是将数字x自乘n - 1次的结果,即将n个x相乘的结果。换言之,power(3, 3)是3自乘两次的结果,即3 × 3 × 3 = 27。

这实现起来很容易。

def power(x, n):
    result = 1
    for i in range(n):
        result *= x
    return result

这是一个简单的小型函数,但也可将定义修改成递归式。

(1).对于任何数字x,power(x, 0)都为1。

(2).n>0时,power(x, n)为power(x, n - 1)与x的乘积。

定义提供的结果与更简单的迭代定义完全相同。

def power(x, n):
    if n == 0
        return 1
    else:
        return x * power(x, n - 1)

三、递归之二分查找

一个常见的问题是:指定的数字是否包含在已排序的序列中?如果包含,在什么位置?为解决这个问题,可采取这样的策略:“这个数字是否在序列中央的右边?” 如果答案是否定的,再问:“它是否在序列的第二个四分之一区间内(左半部分的右边)?” 依次类推。明确数字所处区间的上限和下限,并且每一个问题都将区间分割成两半。

那么该如何做呢?

(1).如果上限和下限相同,就说明它们指向数字所在的位置,因此将此数字返回。

(2).否则,找出区间的中间位置(上限和下限的平均值),再确定数字在左半部分还是在右半部分。然后在继续在数字所在的那部分中查找。

在此递归案例中,关键在于元素是有序的。找出中间元素后,需要将其与要查找的数字进行比较即可。如果查找的数字更大,肯定在右边;如果更小,它必然在左边。

def search(seq, num, lower, upper):
    if lower == upper:
        assert num == seq[upper]
        return upper
    else:
        middle = (lower + upper) // 2
        if num > seq[middle]:
            return search(seq, num, middle + 1, upper)
        else:
            return search(seq, num, lower, middle)

如果lower == upper,就返回upper,即上限。注意,这里假设(断言)找到的确实是要找到的数字(num == seq[upper])。如果还未找到基线条件,就找出中间位置,确定数字在它左边还是右边,再使用新的上限和下限递归地调用search。

为了方便调用还可以将上限和下限设置为可选的。为此,只需给参数lower和upper指定默认值,并在函数开头添加如下条件语句:if upper is None:upper = len(seq) - 1

完整代码如下:

def search(seq, num, lower=0, upper=None):
    if upper is None:
        upper = len(seq) - 1
    if lower == upper:
        assert num == seq[upper]
        return upper
    else:
        middle = (lower + upper) // 2
        if num > seq[middle]:
            return search(seq, num, middle + 1, upper)
        else:
            return search(seq, num, lower, middle)

如果你调用函数时,序列是无序的请先对序列进行排序;也可在search函数的开头加上seq.sort()。

请注意!一定要注意!!!这里使用的序列一定要是有序的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值