基本算法思想(二)

递推算法

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也是一种方法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值