(笔记)计算机科学和PYTHON编程导论——第五讲 递归

课程内容及目标:

  • 讲解递归
  • 展示递归这一概念是如何建立在概念归纳的基础之上的
  • 运用递归引出递归算法的通用原理
  • 分而治之

1.迭代和递归:

计算a*b的值,采用连加的方法:

(1)从迭代的角度来看,表面上,我们可以说这个计算过程只涉及两个变量,一个是迭代次数,设为i,它的初始值应该为b;另一个是状态变量,它计算我们已经进行了多少次运算,现在的结果又是怎样,初始值为0。

由此,状态变量有两个特点:一是如果计算停在任意一点,它们可以准确地告诉我自己的所在位置;二是它们不止可以被初始化,同时至少会有1个状态变量告诉我何时可以终止循环。

def iterMul(a, b):
    result = 0
    while b>0:
        result += a
        b -= 1
    return result

(2)从递归的角度来看,b个a相加,相当于a与b-1个a连加后的结果相加,即a*(b-1)+a。当我们采用递归的思想时,我们做了两件事:首先,我们怎样才能使用已知的方法操作将问题转化成一个更简单的版本,这就是所谓的“递归步骤”;其次,我们将要反复思考如何将计算简化,直到它变得十分简单,我们可以直接解决它,这被称之为“基线条件”。对于这一问题,基线条件是a*b=a;if b=1,否则将执行递归步骤a*b=a+a*(b-1)

def recurMul(a,b):
    if b==1:
        return a
    else:
        return a + recurMul(a, b-1)        


小结:

①每次对函数进行递归调用都会创建它自己的环境,创建变量的局部作用域。因此,在那个环境中,对该函数的主题进行求值需要非常清晰,明确它所使用的a和b的数值以及其他它所使用的变量。

②每一个框架中,变量的绑定都是不同的。并且它们中的每一个都有不同的框架与之对应。而且,当我们进行递归调用时,那些绑定都不会改变。当我们进行调用时,它们就已经设置好了。也就是说,当要计算b的一个新的数值,让它变成b-1,以便在框架中绑定。但进入另一个框架时,将不会改变这些绑定。

③控制流可以很自然地传递回一个更早的框架,只要函数调用返回了它的数值


2.阶乘问题:

(1)迭代:

def factl(n):
    res = 1
    while n>1:
        res = res * n
        n -= 1
    return res

(2)递归:

def factR(n):
    if n == 1:
        return n
    return n*factR(n-1)


3.求base的exp次幂:

①递归:

def recurPower(base, exp):
    if exp == 0:
        return 1
    return base*recurPower(base, exp-1)

②递归进阶:


def recurPowerNew(base, exp):
    if exp == 0:
        return 1
    elif exp>0 and exp%2==0:
        return recurPowerNew(base*base, exp/2)
    elif exp>0 and exp%2!=0:
        return base*recurPowerNew(base, exp-1)


4.求最大公约数:

①采用迭代:

def gcdIter(a, b):
    for i in range(min(a,b), 0, -1):
        if i==1:
            return 1
        if a%i==0 and b%i==0:
            return i

②递归:

利用结论——如果b=0,那么a就是最小公约数,否则,gcd(a,b)=gcd(b,a%b)

def gcdRecur(a,b):
    if b==0:
        return a
    else:
        return gcdRecur(b, a%b)

5.体现递归方法优势的问题——汉诺塔问题:

def printMove(fr, to):
    print('move from '+str(fr)+' to '+str(to))
def Towers(n, fr, to, spare):
    if n == 1:
        printMove(fr, to)
    else:
        Towers(n-1, fr, spare, to)
        Towers(1, fr, to, spare)
        Towers(n-1, spare, to, fr)

6.菲波那切数列:(涉及多个基线条件)

def fib(x):
    assert type(x) == int and x>=0  #assert为断言函数,声明的布尔值必须为真的判定,若为假则返回异常
    if x==0 or x==1:
        return 1
    else:
        return fib(x-1)+fib(x-2)

7.给定一个字符串,判断是否为回文结构:

回文结构:从左向右读和从右向左读一样,如'Able was I ere saw Elba'

第一步是要删除所有的空格和标点符号

第二步将所有字符改为小写

第三步解决问题:

①如果该字符串长度为0或1,那么该字符串就是回文结构

②否则,就要检查,字符串的首尾字母是否相同,然后再看剩下的首尾字母是否相同

def isPalindrome(s):
    
    def toChars(s):
        s = s.lower()
        ans = ''
        for c in s:
            if c in 'abcdefghijklmnopqrstuvwxyz':
                ans = ans + c
        return ans

    def isPal(s):
        if len(s) <= 1:
            return True
        else:
            return s[0]==s[-1] and isPal(s[1:-1])

    return isPal(toChars(s))
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值