首页 > 编程语言 >算法-动态规划

算法-动态规划

时间:2024-05-14 13:40:51浏览次数:18  
标签:递归 int fib 算法 Fibonacci 动态 规划

原文链接:https://blog.csdn.net/u013309870/article/details/75193592

               http://t.csdnimg.cn/GgRFt

动态规划算法的核心

理解一个算法就要理解一个算法的核心,动态规划算法的核心是下面的一个小故事。

A * "1+1+1+1+1+1+1+1 =?" *

A : "上面等式的值是多少"
B : *计算* "8!"

A *在上面等式的左边写上 "1+" *
A : "此时等式的值为多少"
B : *quickly* "9!"
A : "你怎么这么快就知道答案了"
A : "只要在8的基础上加1就行了"
A : "所以你不用重新计算因为你记住了第一个等式的值为8!动态规划算法也可以说是 '记住求过的解来节省时间'"

  由上面的小故事可以知道动态规划算法的核心就是记住已经解决过的子问题的解。

动态规划算法的两种形式

上面已经知道动态规划算法的核心是记住已经求过的解,记住求解的方式有两种:①自顶向下的备忘录法 ②自底向上。

为了说明动态规划的这两种方法,举一个最简单的例子:求斐波拉契数列**Fibonacci **。先看一下这个问题:

Fibonacci (n) = 1;   n = 0

Fibonacci (n) = 1;   n = 1

Fibonacci (n) = Fibonacci(n-1) + Fibonacci(n-2)

  以前学c语言的时候写过这个算法使用递归十分的简单。先使用递归版本来实现这个算法:

public int fib(int n)
{
	if(n<=0)
		return 0;
	if(n==1)
		return 1;
	return fib( n-1)+fib(n-2);
}
//输入6
//输出:8

  先来分析一下递归算法的执行流程,假如输入6,那么执行的递归树如下:

上面的递归树中的每一个子节点都会执行一次,很多重复的节点被执行,fib(2)被重复执行了5次。由于调用每一个函数的时候都要保留上下文,所以空间上开销也不小。这么多的子节点被重复执行,如果在执行的时候把执行过的子节点保存起来,后面要用到的时候直接查表调用的话可以节约大量的时间。下面就看看动态规划的两种方法怎样来解决斐波拉契数列**Fibonacci **数列问题。

①自顶向下的备忘录法

public static int Fibonacci(int n)
{
		if(n<=0)
			return n;
		int []Memo=new int[n+1];		
		for(int i=0;i<=n;i++)
			Memo[i]=-1;
		return fib(n, Memo);
	}
	public static int fib(int n,int []Memo)
	{
		
		if(Memo[n]!=-1)
			return Memo[n];
	//如果已经求出了fib(n)的值直接返回,否则将求出的值保存在Memo备忘录中。				
		if(n<=2)
			Memo[n]=1;
		
		else Memo[n]=fib( n-1,Memo)+fib(n-2,Memo);	
		
		return Memo[n];
	}

备忘录法也是比较好理解的,创建了一个n+1大小的数组来保存求出的斐波拉契数列中的每一个值,在递归的时候如果发现前面fib(n)的值计算出来了就不再计算,如果未计算出来,则计算出来后保存在Memo数组中,下次在调用fib(n)的时候就不会重新递归了。比如上面的递归树中在计算fib(6)的时候先计算fib(5),调用fib(5)算出了fib(4)后,fib(6)再调用fib(4)就不会在递归fib(4)的子树了,因为fib(4)的值已经保存在Memo[4]中。
  

青蛙跳阶:

public class Solution {
    //使用哈希map,充当备忘录的作用
    Map<Integer, Integer> tempMap = new HashMap();
    public int numWays(int n) {
        // n = 0 也算1种
        if (n == 0) {
            return 1;
        }
        if (n <= 2) {
            return n;
        }
        //先判断有没计算过,即看看备忘录有没有
        if (tempMap.containsKey(n)) {
            //备忘录有,即计算过,直接返回
            return tempMap.get(n);
        } else {
            // 备忘录没有,即没有计算过,执行递归计算,并且把结果保存到备忘录map中,对1000000007取余(这个是leetcode题目规定的)
            tempMap.put(n, (numWays(n - 1) + numWays(n - 2)) % 1000000007);
            return tempMap.get(n);
        }
    }
}
复制代码

  

②自底向上的动态规划

备忘录法还是利用了递归,上面算法不管怎样,计算fib(6)的时候最后还是要计算出fib(1),fib(2),fib(3)…,那么何不先计算出fib(1),fib(2),fib(3)…,呢?这也就是动态规划的核心,先计算子问题,再由子问题计算父问题。

 带备忘录的递归解法,空间复杂度是O(n),但是呢,仔细观察上图,可以发现,f(n)只依赖前面两个数,所以只需要两个变量a和b来存储,就可以满足需求了,因此空间复杂度是O(1)就可以啦

public class Solution {
    public int numWays(int n) {
        if (n<= 1) {
            return 1;
        }
        if (n == 2) {
            return 2;
        }
        int a = 1;
        int b = 2;
        int temp = 0;
        for (int i = 3; i <= n; i++) {
            temp = (a + b)% 1000000007;
            a = b;
            b = temp;
        }
        return temp;
    }
    }
复制代码

  

 

标签:递归,int,fib,算法,Fibonacci,动态,规划
From: https://www.cnblogs.com/Dongmy/p/18185610

相关文章

  • 金融市场中的人工智能-新算法和解决方案-全-
    金融市场中的人工智能:新算法和解决方案(全)原文:zh.annas-archive.org/md5/98949b54b6218a075bcbfbd4379f7727译者:飞龙协议:CCBY-NC-SA4.0前言金融市场可能是少数真正可以被描述为复杂系统的人类成就之一。复杂系统是物理学中的结构,它们:(a)从组件之间的相互作用中获得其动态......
  • 42天【代码随想录算法训练营34期】第九章 动态规划part04(● 01背包问题,你该了解这些!
    **416.分割等和子集**classSolution:defcanPartition(self,nums:List[int])->bool:_sum=0dp=[0]*10001fornuminnums:_sum+=numif_sum%2==1:returnfalsetarget=......
  • 洛谷题单指南-动态规划3-P4170 [CQOI2007] 涂色
    原题链接:https://www.luogu.com.cn/problem/P4170题意解读:长度为n的字符串,每次可以将连续一段填为同一个字符,求要填成目标串的最少填涂次数。解题思路:1、状态表示:设s表示目标字符串,dp[i][j]表示将i~j涂成目标"颜色"的最少次数2、状态转移考虑i~j的两端,当i==j,说明只有一个......
  • 代码随想录算法训练营第六天 | 242.有效的字母异位词 、349. 两个数组的交集、 202.
    哈希表理论基础建议:大家要了解哈希表的内部实现原理,哈希函数,哈希碰撞,以及常见哈希表的区别,数组,set和map。什么时候想到用哈希法,当我们遇到了要快速判断一个元素是否出现集合里的时候,就要考虑哈希法。这句话很重要,大家在做哈希表题目都要思考这句话。文章讲解:https://program......
  • 通信算法02
    分集方式1:分集是在多条路径上传输相同的数据,接收端通过分集合并技术,抵抗信道衰落,提高传输可靠性,降低误码率。是指传输多个信号副本来提高接收信号正确判决率的方法。分散传输,集中接收。同一信号,不同通道。常用的分集技术主要有:宏分集和微分集宏分集:多基站分集,用于蜂窝系统的分......
  • 基于高斯混合模型的视频背景提取和人员跟踪算法matlab仿真
    1.算法运行效果图预览    2.算法运行软件版本MATLAB2013B 3.算法理论概述      基于高斯混合模型(GaussianMixtureModel,GMM)的视频背景提取和人员跟踪算法是一种广泛应用的计算机视觉方法,主要用于分离视频序列中的静态背景和动态前景(比如人物运动)。 ......
  • m基于遗传优化的LDPC码OMS译码算法最优偏移参数计算和误码率matlab仿真
    1.算法仿真效果matlab2022a仿真结果如下:   2.算法涉及理论知识概要       低密度奇偶校验码(Low-DensityParity-CheckCodes,LDPCcodes)因其优秀的纠错能力和接近香农极限的性能而广泛应用于现代通信系统中。有序统计译码(OrderedStatisticsDecoding,OSD)......
  • 洛谷题单指南-动态规划3-P1140 相似基因
    原题链接:https://www.luogu.com.cn/problem/P1140题意解读:两个只包含A、C、G、T4个字符的序列,根据已经定义好的字符-字符的相似度,计算两个序列最大的相似度,两个序列必须每个字符都配对,如果字符不够,可以插入'-'代替。解题思路:本题要解决几个问题:1、状态表示既然有两个序列,设......
  • 洛谷题单指南-动态规划3-P1880 [NOI1995] 石子合并
    原题链接:https://www.luogu.com.cn/problem/P1880题意解读:计算n堆石子合并的最小、最大得分,只不过这n堆石子是环形的,也就是首、尾也相邻,是区间DP的升级版-环形DP问题。解题思路:如果是常规区间DP的方法:对于n堆石子,考察区间的长度范围是1~n先枚举左端点i,范围是1~n再计算右......
  • 代码随想录算法训练营day06 | 242.有效字母异位词
    242.有效的字母异位词题目链接文章讲解视频讲解时间复杂度o(n)空间复杂度o(n)classSolution{public:boolisAnagram(strings,stringt){unordered_map<char,int>s_map,t_map;for(charch:s)s_map[ch]++;for(charch:t)t......