• 斐波那契数列——普通递归、尾递归、记忆化搜索、动态规划


    • 普通递归(自顶向下)

      求解F(n),先求解F(n-1)+F(n-2),大量重复计算

      时间复杂度:O(2^n)

      空间复杂度:O(n)

      int fib(int n){
      		if(n == 0){
      			return 0;
      		}
      		
      		if(n == 1){
      			return 1;
      		}
      		
              //避免溢出,返回的结果都模1000000007
      		return fib(n-1) % M + fib(n-2) % M;  
      	}
      
    • 尾递归(自底向上)

      尾递归的一个特点是在回归过程中不用做任何操作,当编译器检测到一个函数使用尾递归的时候,它就覆盖当前的活动记录而不是在栈中去创建新的,这样栈空间大大缩减,从而提升运行效率。

      并且利用了每次递归调用时,都会把之前已经计算好的结果以参数的形式传递过去,避免重复计算

      时间复杂度:O(n)

      空间复杂度:O(n)

      int fib_1(int n, int a, int b){  //a是第n项的值,b是第n+1项的值 
      		if(n == 0){
      			return 0;
      		}
      		
      		if(n == 1){  //从F(1)、F(2)开始 
      			return a;
      		}
      		return fib_1(n-1,b % M,(a+b) % M);  //调用时的a,b的初值是1 1 
      } 
      
    • 记忆化搜索(自顶向下)

      依然是自顶向下的方法,额外开辟一个数组用于保存的计算过的值,使用递归实现,但是避免了重复计算,已经存在存在的值直接返回,计算的都是需要的值

      时间复杂度:O(n)

      空间复杂度: O(n)

      	int fib_2(int n){ 
      		if(n == 0){
      		    return 0;
      	    }
      	    if(n == 1 || n == 2){
      		    return 1;
      	    } 
      	    
      		if(memory[n] == 0){  //已经计算过的直接返回 
      	    	memory[n] = fib_2(n-1) % M  + fib_2(n-2) % M;
      	    } 
         	    return memory[n];  
      	} 
      
    • 动态规划

      初始状态: dp[0] = 0 dp[1] = 1, 定义状态转移方程:dp[n] = dp(n-1) + dp[n-2]

      时间复杂度:O(n)

      空间复杂度:O(n)

      int fib_3(int n){
      		if(n < 0){
      			return -1;
      		}
      		memory[0] = 0;
      		memory[1] = 1;
      		for(int i = 2;i <= n;i++){
      			memory[i] = memory[i-1] % M + memory[i-2] % M;   
      		}
      		return memory[n];
      	} 
      
    • 动态规划的空间复杂度优化

      使用三个变量交替前进,代替了使用一个dp数组,将空间复杂度降到O(1),时间复杂度还是O(n)

      int fib_4(int n) {
          	if(n == 0){
          		return 0;
      		}
      		int temp,a1=1,a2=1;  //从n==1开始计算 
              for(int i = 1;i < n;i++){ 
              	temp = a2;
              	a2 = (a1+a2) % M;  //加的是下一次的结果 
              	a1 = temp;  //返回的是上次加的结果 
      		}
      		return a1;
          }
      
  • 相关阅读:
    MySQL 多列索引优化小记
    Spring MVC + Security 4 初体验(Java配置版)
    Java程序通过代理访问网络
    Spring RESTful + Redis全注解实现恶意登录保护机制
    WinSCP 中普通用户以 root 身份登录 Linux
    Linux下修改系统时区
    Git如何检出指定目录或文件
    朴素贝叶斯
    console.log 被重写覆盖以后如何恢复
    MongoDB 基础命令使用学习记录
  • 原文地址:https://www.cnblogs.com/Vicky1361/p/14577810.html
Copyright © 2020-2023  润新知