• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

cynchanpin

  • 博客园
  • 联系
  • 订阅
  • 管理

View Post

算法学习笔记(五) 递归之 高速幂、斐波那契矩阵加速

递归的定义

递归和迭代是编程中最为经常使用的基本技巧。并且递归经常比迭代更为简洁和强大。它的定义就是:直接或间接调用自身。经典问题有:幂运算、阶乘、组合数、斐波那契数列、汉诺塔等。

其算法思想:

  • 原问题可分解子问题(必要条件);
  • 原与分解后的子问题相似(递归方程);
  • 分解次数有限(子问题有穷);
  • 终于问题可直接解决(递归边界);

对于递归的应用与优化,直接递归时要预估时空复杂度。以免出现用时过长或者栈溢出。优化递归就是以不做反复的事儿为原则进行。对于常见数列问题。经常会有递推公式。也即 f(n) 和 f(n-1) 的关系式,由递推公式事实上就非常easy写出递归算法的代码,这里要又一次具体说一下递归和递推的差别:

  • 递归:将问题规模为n的问题,降解成若干个规模为n-1的问题,依次降解,直到问题规模可求。求出低阶规模的解,代入高阶问题中。直至求出规模为n的问题的解, ( n  ->  0)。
  • 递推:构造低阶的规模(如规模为i,一般 i=0 ) 的问题。并求出解,推导出问题规模为i+1的问题以及解,依次推到规模为n的问题。 (0  ->  n);

高速幂


直接转换成代码。时间复杂度由朴素幂运算的 O(n) -> O(logn) :

/* a 的  n 次方的高速幂,C 代码 */
int quickpower(int a, int n) {
	if (n == 0)
		return 1;

	if (n % 2 == 1)
		return quickpower(a, n / 2) * quickpower(a, n / 2) * a;
	else
		return quickpower(a, n / 2) * quickpower(a, n / 2);
}

斐波那契数列


转换为代码,时间复杂度由直接递归的 O(n^2) -> O(logn) , 以下的实验用 Python 实现,假设用 C++ 重载乘法运算符。则能够非常大程度复用高速幂代码了就:

from time import clock
from functools import reduce

# 递归计算斐波那契数列 , python3 实现
def fib1(n):
    if n <= 1 :
        return 1
    else :
        return fib1(n - 1) + fib1(n - 2)

# 计算 a, b (都是 2×2 的矩阵) 的乘积 
def mul(a, b):
    r = [[0, 0], [0, 0]]
    r[0][0] = a[0][0] * b[0][0] + a[0][1] * b[1][0];
    r[0][1] = a[0][0] * b[0][1] + a[0][1] * b[1][1];
    r[1][0] = a[1][0] * b[0][0] + a[1][1] * b[1][0];
    r[1][1] = a[1][0] * b[0][1] + a[1][1] * b[1][1];
    return r;

# 递归加速计算斐波那契数列 O(n^2) -> O(logn)
def fib(n):
    if n == 0:
        return [[1, 0], [0, 1]]
    if n == 1:
        return [[1, 1], [1, 0]]
    if n % 2 == 0 :
        return mul(fib(int(n / 2)), fib(int(n / 2)))
    else:
        return reduce(mul,[fib(int(n / 2)),fib(int(n / 2)),[[1, 1], [1, 0]]])

if __name__ == '__main__':
    starttime = clock()
    print(fib1(35))  
    endtime = clock()
    print('直接计算用递归:', endtime - starttime)
    starttime = clock()
    print(fib(35)[0][0])
    endtime = clock()
    print('矩阵递归幂加速:', endtime - starttime)

''' 
试验执行结果:
14930352
直接计算用递归: 5.524596036360783
14930352
矩阵递归幂加速: 0.00015129910309763517
'''

【原文地址:http://blog.csdn.net/thisinnocence】

posted on 2017-06-13 18:03  cynchanpin  阅读(430)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3