递归算法之“青蛙跳台阶”以及“整数划分”的python实现

青蛙跳台阶:

问题描述:

(1)一只青蛙一次可以跳上 1 级台阶,也可以跳上2 级。求该青蛙跳上一个n 级的台阶总共有多少种跳法。

(2)一只青蛙一次可以跳上1级台阶,也可以跳上2 级……它也可以跳上n 级,此时该青蛙跳上一个n级的台阶总共有多少种跳法?

分治法的设计思想是,将一个难以直接解决的大问题,分割成一些规模较小的相同问题,已便各个击破,分而治之。 

思路:

假设:用 f(n) 表示青蛙跳上n阶台阶的跳法数。

对于问题(1)青蛙在跳上第n个台阶之前,因为青蛙只能跳1级台阶或者是2级台阶,所以只有两种情况,即一是青蛙在第n-1个台阶上;二是青蛙在第n-2个台阶上。

        则 f(n)= f(n-1)+ f(n-2)。递归结束的条件为为 f(1)= 1;以及 f(2)=2。

python代码如下:

def fogjump(n):
    if n == 1 or n == 0:
        return 1
    if n == 2:
        return 2
    if n > 2:
        return fogjump(n-1) + fogjump(n-2)

if __name__ == "__main__":
    print(fogjump(5))

对于问题(2),青蛙在上第n哥台阶之前,因为青蛙可以跳  1~n 级,所以有n种情况。青蛙在第n-1个台阶上;青蛙在第n-2个台阶上;青蛙在第n-3个台阶上......;青蛙在第2个台阶上;青蛙在第1个台阶上上。

则 f(n) = f(n-1) + f(n-2) + f(n-3) +......f(2)+f(1) 

又f(n-1) = f(n-2) + f(n-3) +......f(2)+f(1) 

两式相减,得递归式为:f(n) = 2*f(n-1)

递归结束的条件为为 f(1)= 1。

python代码如下:

def fogjump(n):
    if n == 1 or n == 0:
        return 1
    if n > 1:
        return 2*fogjump(n-1)

if __name__ == "__main__":
    print(fogjump(5))

整数划分问题 :

问题描述:

将正整数 n 表示成一系列正整数之和,即 n = n1 + n2 + ......+nk (其中n1 >= n2>=...>=nk>=1,k >=1)。正整数 n 的这种表示称为正整数 n 的划分。正整数 n 的不同划分个数称为正整数 n  的划分数,记做 p(n)。

例如:正整数 6 有如下11种不同的划分,所以 p(6) = 11

6;

5+1;

4+2,4+1+1;

3+3,3+2+1,3+1+1+1;

2+2+2,2+2+1+1,2+1+1+1+1;

1+1+1+1+1+1。

在正整数 n  的所有划分中,将不大于 m 的划分个数记为 p(n, m),其中 m 为最大加数

根据n和m的关系,考虑以下几种情况: 建立 p(n, m) 的如下递归关系。

(1)当 m = 1 时,p(n, 1) = 1 , n >=1。当最大加数为 1 时,任何正整数 n 只有一种划分形式,即 n = 1 +1 +1+......+1;

(2)当n=1 时,p(1,m) = 1,不论m的值为多少(m>0),只有一种划分,即{1};

(3)当 n < m 时,p(n, m) = p (n, n) 。 最大加数不能大于n,划分中不可能出现负数,因此就相当于p(n,n)

  (4)  当 n=m 时,根据划分中是否包含最大加数n,可以分为两种情况:

              (a). 划分中包含最大加数n的情况,只有1个,即{n};

              (b). 划分中不包含最大加数n的情况,这时划分中最大的加数一定比n小,即 n 的所有 (n-1) 划分。

              因此 p(n, n) =1 + p(n, n-1);

 (5) 当 n>m 时,根据划分中是否包含最大加数m,可以分为两种情况:

               (a). 划分中包含最大加数m的情况,即{m, {x1,x2,...xi}}, 其中{x1,x2,... xi} 的和为 n-m,可能再次出现m,因此是(n-m)的m划分,因此这种划分的个数为 p(n-m, m);

               (b). 划分中不包含最大加数m的情况,则划分中所有值都比 m 小,即 n 的 (m-1) 划分,个数为 p(n,m-1);

              因此 p(n, m) = p(n-m, m) + p(n, m-1);

综合以上情况,我们可以看出,上面的结论具有递归定义特征,其中(1)和(2)属于递归结束条件,(3)和(4)属于特殊情况,将会转换为情况(5)。而情况(5)为通用情况,属于递推的方法,其本质主要是通过减小m以达到递归结束条件,从而解决问题。其递推表达式如下:

                                             {\color{Red} }\left\{\begin{matrix} 1 & n=1 &or ,m =1\\ p(n, n) & n < m\\ 1+p(n,n-1) &n = m \\ p(n,m-1)+p(n-m,m) &n>m>1 \end{matrix}\right.

 python代码实现如下:

def divide(n, m):
    if (n == 1) or (m == 1):
        return 1
    if n < m:
        return divide(n, n)
    if n == m:
        return divide(n, n-1) + 1
    if n > m > 1:
        return divide(n, m-1) + divide(n-m, m)

if __name__ == '__main__':
    a = int(input())
    print(divide(a, a))

 

 

 

 

  • 1
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值