算法笔记:递归、动态规划
目录
- 递归、分治和动态规划
- 德罗斯特效应
- 递归、分治和动态规划
- 迭代和递归的区别
- 分治
- 动态规划
- 解法
- 斐波那契数
- 解法1:暴力递归
- 解法2:记忆化存储
- 解法3:动态规划
- 解法4:自底向上迭代
动态规划是求解决策过程最优化的过程,可以高效求解那些可以分解为高度重复子问题的问题,应用非常广泛,比如解决最短路线、NLP等实际问题。
递归、分治和动态规划
德罗斯特效应
德罗斯特效应(Droste effect)是递归艺术中的一种表现形式,德罗斯特效应即在一幅图像中,某个局部图像与整体图像类似,而在这个局部中,又有更小的部分与这个局部类似,依次类推且可无限重复。
德罗斯特(Droste)可可粉的包装盒
德罗斯特是荷兰的一个著名巧克力品牌,创立于1863年,上面这张图片从1904年起开始使用,数十年间只进行了一些小幅的调整,后来成为一个家喻户晓的概念。诗人及专栏作家Nico Scheepmaker在七十年代起,开始使用“德罗斯特效应”此一词语。下面介绍动态规划算法。
递归、分治和动态规划
迭代和递归的区别
- 迭代是将输出作为输入,再次进行处理。
- 递归,自己调用自己,自己包含自己。
分治
分治( Divide &Conquer )是将问题分解为若干个子问题(Divide),递归求解这些子问题(Conquer),然后合并子问题的解。
动态规划
动态规划(Dynamic Programming)和分治策略类似,也是将原问题分解为若干子问题,递归的求解这些子问题,然后合并子问题的解得到原问题的解。
通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量:一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。(维基百科:动态规划)
通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,从而减少计算量。动态规划、递归和分治没有根本上的区别,解法都是先找到重复的子问题,也就是将问题拆解成可重复解决的问题。
解法
递归问题解法:
- 找到重复子问题
- 确定递归终止条件
对于动态规划问题,每个子问题只求解一次,注意将其结果保存起来,进行记忆化存储。
斐波那契数
斐波那契数列LeetCode地址:https://leetcode-cn.com/problems/fibonacci-number/
解法1:暴力递归
class Solution:def fib(self, n):if n <= 0:return 0elif n == 1:return 1else:return self.fib(n - 1) + self.fib(n - 2)
if __name__ == "__main__":solu = Solution()result = solu.fib(6)print(result)
结果:
8
时间复杂度:O(2^N)
空间复杂度:O(N)
如果数比较大,2^N的时间复杂度将会占用大量资源,计算非常慢。其实暴力递归计算过程中,进行了大量重复计算,我们来看一下Fib(6)的状态树:
我们发现f(4)计算了2次,f(3)计算了3次,其实没必要重复计算,可以使用记忆化存储来保存计算值。
解法2:记忆化存储
class Solution:def fib(self, n):cash = {0:0,1:1}def memoize(n):if n in cash:return cash[n]cash[n] = memoize(n - 1) + memoize(n - 2)return cash[n]return memoize(n)
if __name__ == "__main__":solu = Solution()result = solu.fib(6)print(result)
时间复杂度:O(N)
空间复杂度:O(N)
解法3:动态规划
class Solution: def fib(self, n): if n <= 1: return ndp = [0, 1] + [0]*(n-1)for i in range(2, n+1):dp[i] = dp[i-1] + dp[i-2]return dp[i]if __name__ == "__main__":solu = Solution() result = solu.fib(6) print(result)
时间复杂度:O(N)
空间复杂度:O(N)
解法4:自底向上迭代
可以进一步减少空间复杂度
class Solution: def fib(self, n): if n <= 1: return na, b = 0, 1for _ in range(1, n):c = a + ba, b = b, creturn cif __name__ == "__main__": solu = Solution() result = solu.fib(6) print(result)
时间复杂度:O(N)
空间复杂度:O(1)
--THE END--
欢迎关注公众号:「测试开发小记」及时接收最新技术文章!
算法笔记:递归、动态规划相关推荐
- 《算法笔记》中文版 - 包括数组,链表,树,图,递归,DP,有序表等相关数据结构与算法的讲解及代码实现...
来源:专知本文为资源,建议阅读5分钟本文为你分享<算法笔记>中文版. https://github.com/Dairongpeng/algorithm-note 目录概览 第一节 复杂度. ...
- python数据结构和算法 时间复杂度分析 乱序单词检测 线性数据结构 栈stack 字符匹配 表达式求值 queue队列 链表 递归 动态规划 排序和搜索 树 图
python数据结构和算法 参考 本文github 计算机科学是解决问题的研究.计算机科学使用抽象作为表示过程和数据的工具.抽象的数据类型允许程序员通过隐藏数据的细节来管理问题领域的复杂性.Pytho ...
- >算法笔记-动态规划-最短路径迪杰斯特拉算法
算法笔记-动态规划-最短路径迪杰斯特拉算法 作者:星河滚烫兮 前言 图的最短路径问题在现实生活中有很广阔的应用,最短路径又分为单源最短路径与多源最短路径,前者求出固定起点到其他节点的最短路径,后者 ...
- [算法入门笔记] 18. 动态规划
动态规划往往是有套路的,但套路是建立在熟练的基础上的~ 文章目录 0 建议 1 机器人达到指定位置的方法数 1.1 暴力递归 1.2 记忆化搜索 1.3 动态规划 2 换钱的最少货币数 2.1 暴力递 ...
- 数据结构与算法笔记 - 绪论
数据结构与算法笔记 - 绪论 1. 什么是计算 2. 评判DSA优劣的参照(直尺) 3. 度量DSA性能的尺度(刻度) 4. DSA的性能度量的方法 5. DSA性能的设计及其优化 x1. 理论模型与 ...
- 算法笔记(胡凡)学习笔记@Kaysen
本文旨在记录算法笔记学习过程中的收获和一些知识点,部分易错知识点只针对个人而言,CCF-CSP考试冲鸭!!! Chapter 2 C/C++快速入门(易错知识点) 2.1 基本数据类型 变量定义注意区 ...
- 明翰数据结构与算法笔记V0.8(持续更新)
文章目录 前言 数据结构 `线性表` `数组` `链表` `栈与队列` [串/字符串] 树 并查集 `二叉树` [二叉排序树/二叉搜索树] `红黑树` 红黑树操作 霍夫曼树 `堆` [大/小]根堆 可 ...
- codeup墓地目录(算法笔记习题刷题笔记)
在线codeup contest 地址:http://codeup.cn/contest.php Contest100000575 - <算法笔记>3.1小节--入门模拟->简单模拟 ...
- 【算法笔记】极客时间 算法面试通关40讲 笔记 覃超
[算法笔记]极客时间 算法面试通关40讲 覃超 [算法笔记]极客时间 算法面试通关40讲 覃超 相关链接 在leetcode 上的题号 数组.链表: (堆)栈stack.队列queue 优先队列 哈希 ...
最新文章
- php – Laravel 7 Session Lifetime
- 玩转百度地图(二)之画圆,高德地图、搜搜地图、搜狗地图等稍微修改即可...
- python实现isodd函数、参数为整数、如果整数为奇数_python 程序练习题
- Linux内核开发之异步通知与异步I/O《来自linux设备开发详解》
- LeetCode-108将有序数组转换为二叉搜索树
- Python下json中文乱码解决办法
- paypal注册流程
- Verilog——三角波发生器(状态机)
- 【转】常用邮箱的 IMAP/POP3/SMTP 设置
- 直播推流方案及过程分解
- 针对phpStudy网站服务器的入侵
- 极具挑战性的工作:升级模式库从CQ2002到CQ7
- Android获取手机屏幕像素大小
- 扩充计算机内存是扩充什么,怎样扩大电脑内存 电脑扩大内存方法【图文】
- mysql 连续七天不登录_【SQL】查询连续登陆7天以上的用户
- 前端笔记 (持续更新~)
- 机器学习——经典降维算法与框架综述
- 记第一次写出自己的简单python爬虫:GCZW3
- ecnu-2020寒假热身-01
- GoFrame框架快速入门教程