算法-动态规划

news/2024/9/22 18:31:31

原文链接: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 = 0Fibonacci (n) = 1;   n = 1Fibonacci (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;}}
复制代码

  

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ryyt.cn/news/31382.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈,一经查实,立即删除!

相关文章

[转帖]国产主流数据库存储类型简析

https://blog.csdn.net/solihawk/article/details/137807944国产数据库在技术架构上主要分为集中式、基于中间件分布式和原生分布式架构,衍生出集中式架构和分布式架构。那么在这些部署架构中,从数据分布的视角来看,在数据库中数据分布的形态是怎样的。本文将简要分析OceanB…

第 4篇 Scrum 冲刺博客

这个作业属于哪个课程 软件工程2024这个作业要求在哪里 团队作业4——项目冲刺这个作业的目标 记录敏捷流程下第四天的项目开发进展,对团队昨日的项目进度进行总结一、每日站立式会议 1、每日站立式会议照片2、会议摘要本次会议为第四次Scrum Meeting会议~ 由于本次会议队长召…

数据库升级PostgreSql+Garnet

目录前言PostgreSql安装测试额外Nuget安装Person.cs模拟运行Navicate连postgresql解决方案Garnet为什么要选择Garnet而不是RedisRedis不再开源Windows版的Redis是由微软维护的Windows Redis版本老旧,后续可能不再更新Garnet性能强于Redis安装测试安装可视化工具C# 代码连接测试…

Vue学习知识汇总

官网:https://cn.vuejs.org/ 前置知识:完整的学习vue: html + css、JavaScript、css3、HTML5、第三方库、网络通信、ES6+、webpack、模块化、包管理器、css预编译器 体验vue功能:html + css、JavaScriptVue拥有以下特点:渐进式 组件化 响应式Vue的应用场景:前台的部分页面 中…

玩转创想三维 K1 系列主板之二:编译 MCU 固件,恢复裁剪组件

前言 原创文章,转载引用请务必注明链接,水平有限,如有疏漏,欢迎交流指正。 文章如有更新请访问 DFRobot 社区 及 cnblogs 博客园,前者内容较全,后者排版及阅读体验更佳。 本文是摸索创想三维 K1 系列软硬件系统的一些内容分享。最近创想三维的工作人员联系了我,希望接下…

第 3篇 Scrum 冲刺博客

这个作业属于哪个课程 软件工程2024这个作业要求在哪里 团队作业4——项目冲刺这个作业的目标 记录敏捷流程下第三天的项目开发进展,对团队昨日的全员学习进度进行总结一、每日站立式会议 1、每日站立式会议照片2、会议摘要本次会议为第三次Scrum Meeting会议~ 由于本次会议队…

nacos接口使用

1.nacos官方文档https://nacos.io/zh-cn/docs/open-api.html 2.参数获取 3.nacos例子(其余例子可参考文档)#调用api发布配置 curl -X POST -F "file=@cv-platfom-common.yaml" -F "content=$(<cv-platfom-common.yaml)" -F "type=yaml" &…

java split用法 案例

需求:java读取一个csv文件并将文件内容每行按照","隔开 场景一: 读取1.csv文件:文件内容如下: 1,zhangsan,note2,lisi, 注意:第二行逗号后面没有数据public static void main(String[] args) {String csvFile = "C:\\Users\\yc\\Desktop\\1.csv";Stri…