递推算法
1.递推算法概述
- 递推/递归既可以理解成是一种算法思想,也可以理解成是一种算法的实现方式
- 分治算法策略主要通过递归实现,大规模问题分解成小规模问题;动态规划算法主要通过递推实现
- 递归和递推的核心其实都是递推式
- 递归:从上到下 从未知到已知解决问题
- 递推:从下到上 从已知到未知解决问题
(1)算法特点:
一个问题的求解需一系列的计算
在已知条件和所求问题之间总存在着某种相互联系的关系
找到前后过程之间的数量关系(即递推式),分为顺推和逆推。
无论顺推还是逆推,其关键是要找到递推式
(2)关键:
用递推算法解决问题时,关键是找到递推式以及边界条件(临界条件)
(3)顺推、逆推
(4)使用递推方法解决:
菲波那契数列、汉诺塔移动次数、猴子吃桃、数字三角形(顺推法)、骨牌铺满方格、蜜蜂路线、吃糖果、昆虫繁殖、位数问题、分苹果、踩方格、爬楼梯(openjudge题目)
2.求菲波那契数列
(Fibonacci)数列的前40个数。这个数列有如下特点:第1、2两个数为1、1。从第3个数开始,该数是其前面两个数之和。即:
3.C语言实现
#include <stdio.h>
#include <stdlib.h>
int Fibonacci(n) //兔子产仔算法
{
int t1,t2;
if(n==1||n==2)
{
return 1;
}
else
{
t1=Fibonacci(n-1);
t2=Fibonacci(n-2);
return t1+t2;
}
}
void main()
{
int n,num;
printf("递推算法求解兔子产仔问题!\n");
printf("请先输入时间:");
scanf("%d",&n);
num=Fibonacci(n);
printf("经过%d个月的时间,共能繁殖成%d对兔子!\n",n,num);
}
4.C++语言实现
#include<iostream>
using namespace std;
int main()
{
int f[101],n;
cin>>n;
f[1]=1;f[2]=1;
for(int i=3;i<=n;i++)
f[i]=f[i-1]+f[i-2];
for(int i=0;i<n;i++)
{
if(i%5==0)//5个数一行
cout<<endl;
cout<<f[i]<<'\t';
}
cout<<endl;
return 0;
}
5.Java语言实现
package com.xxx.huali.hualitest.fibonacci;
public class Main {
/***
* 递归思想
* 时间复杂度O(n*n)
* @param n
* @return
*/
public static long fib1(int n) {
if(n<1)
return -1;
if(n==1||n==2)
return 1;
return fib1(n-2)+fib1(n-1);
}
/**
* 引入一个数组,计算每一项的值
* 时间复杂度O(n)
* 空间复杂度O(n)
* @param n
* @return
*/
public static long fib2(int n) {
if(n<1)
return -1;
long[] data = new long[n+1];
data[1] = 1;
data[2] = 1;
for(int i=3;i<=n;i++)
data[i] = data[i-1] + data[i-2];
return data[n];
}
/***
* 动态规划思想,迭代计算
* 时间复杂度O(n)
* 空间复杂度O(1)
* @param n
* @return
*/
public static long fib3(int n) {
long i,a,b;
if(n<1)
return -1;
if(n==1||n==2)
return 1;
a = 1;
b = 1;
for(i=3;i<=n;i++) {
b = a + b;
a = b - a;
}
return b;
}
/***
* 根据推导公式计算
* 特征方程x^2 = x+1
* @param n
* @return
*/
public static long fib4(int n) {
double result = 0;
double sqrt5 = Math.sqrt(5);
result = (Math.pow((1+sqrt5)/2, n)-Math.pow((1-sqrt5)/2,n))/sqrt5;
return (long)result;
}
/***
* 矩阵快速幂算法
* 时间复杂度O(logn)
* @param n
* @return
*/
public static long fib5(int n) {
if(n<1)
return -1;
if(n==1||n==2)
return 1;
long[][] result = {{1},{0}};
long[][] tem = {{1,1},{1,0}};
while(n!=0) {
if((n&1)==1)
result = matrixMultiply(tem, result);
tem = matrixMultiply(tem, tem);
n>>=1;
}
return result[1][0];
}
public static long[][] matrixMultiply(long[][] a,long[][] b){
int rows = a.length;
int cols = b[0].length;
long[][] matrix = new long[rows][cols];
for(int i=0;i<rows;i++) {
for(int j=0;j<cols;j++) {
for(int k=0;k<a[i].length;k++) {
matrix[i][j] += a[i][k] * b[k][j];
}
}
}
return matrix;
}
public static void main(String[] args) {
int n = 71;
//System.out.println(fib1(n));
System.out.println(fib2(n));
System.out.println(fib3(n));
System.out.println(fib4(n));
System.out.println(fib5(n));
System.out.println("---------------");
n = 72;
//System.out.println(fib1(n));
System.out.println(fib2(n));
System.out.println(fib3(n));
System.out.println(fib4(n));
System.out.println(fib5(n));
}
}
6.Python语言实现
(1)递归法
def fib_recur(n):
assert n >= 0, "n > 0"
if n <= 1:
return n
return fib_recur(n-1) + fib_recur(n-2)
for i in range(1, 20):
print(fib_recur(i), end=' ')
(2)递推法
def fib_loop(n):
a, b = 0, 1
for i in range(n + 1):
a, b = b, a + b
return a
for i in range(20):
print(fib_loop(i), end=' ')
(3)生成器
def fib_loop_while(max):
a, b = 0, 1
while max > 0:
a, b = b, a + b
max -= 1
yield a
for i in fib_loop_while(10):
print(i)
(4)类实现内部魔法方法
class Fibonacci(object):
"""斐波那契数列迭代器"""
def __init__(self, n):
"""
:param n:int 指 生成数列的个数
"""
self.n = n
# 保存当前生成到的数据列的第几个数据,生成器中性质,记录位置,下一个位置的数据
self.current = 0
# 两个初始值
self.a = 0
self.b = 1
def __next__(self):
"""当使用next()函数调用时,就会获取下一个数"""
if self.current < self.n:
self.a, self.b = self.b, self.a + self.b
self.current += 1
return self.a
else:
raise StopIteration
def __iter__(self):
"""迭代器的__iter__ 返回自身即可"""
return self
if __name__ == '__main__':
fib = Fibonacci(15)
for num in fib:
print(num)
(5)矩阵快速幂
import numpy as np
### 1
def fib_matrix(n):
for i in range(n):
res = pow((np.matrix([[1, 1], [1, 0]], dtype='int64')), i) * np.matrix([[1], [0]])
print(int(res[0][0]))
# 调用
> fib_matrix(50)
### 2
# 使用矩阵计算斐波那契数列
def Fibonacci_Matrix_tool(n):
Matrix = np.matrix("1 1;1 0", dtype='int64')
# 返回是matrix类型
return np.linalg.matrix_power(Matrix, n)
def Fibonacci_Matrix(n):
result_list = []
for i in range(0, n):
result_list.append(np.array(Fibonacci_Matrix_tool(i))[0][0])
return result_list
# 调用
> Fibonacci_Matrix(50)
### pow 速度 比 双**号快, np.linalg.matrix_power也是一种方法