数据解构+算法(第07篇):动态编程!黄袍加身!

news2024/11/26 14:35:06

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

学习必须往深处挖,挖的越深,基础越扎实!

阶段1、深入多线程

阶段2、深入多线程设计模式

阶段3、深入juc源码解析


阶段4、深入jdk其余源码解析


阶段5、深入jvm源码解析

码哥源码部分

码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】

码哥讲源码【炸雷啦!炸雷啦!黄光头他终于跑路啦!】

码哥讲源码-【jvm课程前置知识及c/c++调试环境搭建】

​​​​​​码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】

码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】

码哥讲源码【你水不是你的错,但是你胡说八道就是你不对了!】

码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】

终结B站没人能讲清楚红黑树的历史,不服等你来踢馆!

打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】 

引言

在上篇文章《再不会"降维打击"你就Out了!》中,提到了递归算法的两个局限性。本文给出解决方案——动态编程。如果说"递归算法"是圣剑的话,那么"动态编程"就是圣衣。两者加持,你便可以爆发究极小宇宙:)

递归算法局限性详细分析

局限性1(适用性问题):

如果“降维”前的状态集合并不方便用“降维”后的状态集合表示,即状态转移函数不好求,那么该场景使用递归不一定恰当。

下面举个例子来说明:

有两个集合ABA中有n个元素,B中也有n个相同元素,将A中的元素通过映射f,映射到B中的元素,映射f满足:f(f(x))=f(x),求这样的不同映射有多少种。

根据在《再不会"降维打击"你就Out了!》中讲到的递归应用的优化套路,很容易看出,规模因子就是n,关键要求的就是状态转移函数g:f(n-1)->f(n)

f(n-1)表示A和B各有n-1个元素时,不同映射的种数;

f(n)表示A和B各有n个元素时,不同映射的种数。

上图左侧表示的就是f(n-1)对应的一种情况,右侧表示的就是f(n)对应的一种情况。

在上面图示的情况中:

元素个数等于n-1时,A中的元素K2映射到B中的元素Kn-1

但是元素个数等于n时,A中的元素K2映射到B中的元素Kn,此时映射的种数等价于下图映射的种数:

这是一个n-2个元素到n-1个元素的映射,显然它的值不一定等于f(n-1)

换言之,在本例中,f(n)并不方便用f(n-1)来表示,即状态转移函数g:f(n-1)->f(n)不好求。

原因就是:

问题规模变化时,“形状”变了——从(n-1)->(n-1)变成了(n-2)->(n-1)——直观地说,从“正方形”变成了“梯形”。

如果仍然要用递归来解,那么就需要引入中间态辅助函数,计算“梯形”的函数值。

局限性2(重复计算问题):

在直接递归的过程中部分函数值会被重复计算

为了避免重复计算,一个直接而朴素的想法就是:引入中间态辅助函数,将算过的函数值存下来,递归时再次遇到该函数时,直接从保存结果中取出来。

从上面对两个局限性的分析可以看出:优化递归的方法就是引入中间态辅助函数,保存中间态结果。

这种方法就叫做“动态编程”。

自顶向下 vs. 自底向上

很明显,保存中间态结果,有两种方式——自顶向下或者自底向上。

还是拿《再不会"降维打击"你就Out了!》中的爬台阶的例子来讲。

最终的状态转移函数表达式如下:

当n>=4时:

f(n)=f(n-1)+f(n-2)+f(n-3)

1<=n<4时:f(n)=n

当n<1时:f(n)=0

递归的自然方向就是自顶向下。递归的同时,首先查一下保存函数值的线性表,如果查得到,那么就直接“拿来主义”;

如果查不到,那么计算完了函数值之后,也往线性表里保存结果,这样后面的递归步骤如果用得上的话,就节省计算时间了。

这里的线性表是不是有点像“备忘录”呢?所以这个方法也称作“备忘录法”

下面再来看看自底向上。我们逆着递归自然展开的方向,根据状态转移函数,一边查表一边从底部向上逐步计算函数值,并将新计算出来的值也保存到线性表中,供更高层的函数值计算时使用。这种方法就叫做“动态规划”。

由于“动态规划”是逆着递归自然展开的方向,所以写出开的程序结构不再是递归形式,而是递归展开的反向形式——循环结构。

进一步优化

细心的同学肯定发现了:无论是“备忘录法”还是“动态规划”,都要保存所有的中间结果,这必将导致空间复杂度极大。

那么如何优化呢?

还是拿上面的爬台阶的例子来说明。根据上面的树状图示,显然每次求当前层的函数值时,只会用到紧邻的下一层的几个函数值,这意味着更深层的函数值都没有用了,可以舍去、释放内存。

换言之,无论是使用“备忘录法”还是“动态规划”,都要分析状态转移函数,看看“降维”前后到底涉及哪些状态,不在这个状态集合里的函数值都可以舍去、释放内存。

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

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

相关文章

【数据分享】1929-2023年全球站点的逐月最高气温数据(Shp\Excel\无需转发)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、湿度等指标&#xff0c;其中又以气温指标最为常用&#xff01;说到气温数据&#xff0c;最详细的气温数据是具体到气象监测站点的气温数据&#xff01; 之前我们分享过1929-2023年全球气象站…

vue如何使用vuedraggable实现不同面板之间的拖拽排序,拖拽复制功能?【vuedraggable】

vuedraggable官方文档链接使用说明https://www.itxst.com/vue-draggable/re7vfyfe.htmlhttps://www.itxst.com/vue-draggable/re7vfyfe.html 效果图&#xff1a; 使用vuedraggable拖动左边的字段和逻辑到右边形成不同的规则校验 <!-- ****--date 2024-02-01 11:34****-…

私募证券基金动态-23年12月报

成交量&#xff1a;12月日均7,696.93亿元 2023年12月A股两市日均成交7,696.93亿元&#xff0c;环比下降12.39%、同比下降2.26%。12月整体21个交易日&#xff0c;无单日交易日成交金额过万亿&#xff0c;单日交易日最低成交金额为6,122.84亿元&#xff08;12月25日&#xff09;…

GPT-4 Vision调试任何应用,即使缺少文本日志 升级Streamlit七

GPT-4 Vision 系列: 翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式一翻译: GPT-4 with Vision 升级 Streamlit 应用程序的 7 种方式二翻译: GPT-4 Vision静态图表转换为动态数据可视化 升级Streamlit 三翻译: GPT-4 Vision从图像转换为完全可编辑的表格 升级St…

【C/Python】GtkApplicationWindow

一、C语言 GtkApplicationWindow 是 GTK 库中用于创建应用程序主窗口的一个控件。 首先&#xff0c;需要确保环境安装了GTK开发库。然后&#xff0c;以下是一个简单的使用 GtkApplicationWindow 创建一个 GTK 应用程序的示例&#xff1a; #include <gtk/gtk.h>static …

前端JavaScript篇之let、const、var的区别

目录 let、const、var的区别 let、const、var的区别 let、const和var是JavaScript中用于声明变量的关键字&#xff0c;它们之间有一些区别。 首先&#xff0c;var是在ES5中引入的关键字&#xff0c;而let和const是在ES6中引入的。在ES6之前&#xff0c;我们只能使用var来声明…

Thinkphp5.0.23远程代码执行漏洞复现

★★免责声明★★ 文章中涉及的程序(方法)可能带有攻击性&#xff0c;仅供安全研究与学习之用&#xff0c;读者将信息做其他用途&#xff0c;由Ta承担全部法律及连带责任&#xff0c;文章作者不承担任何法律及连带责任。 1、漏洞介绍 使用Thinkphp5.x远程代码执行漏洞&#xf…

操作系统--进程、线程基础知识

一、进程 我们编写的代码只是一个存储在硬盘的静态文件&#xff0c;通过编译后就会生成二进制可执行文件&#xff0c;当我们运行这个可执行文件后&#xff0c;它会被装载到内存中&#xff0c;接着 CPU 会执行程序中的每一条指令&#xff0c;那么这个运行中的程序&#xff0c;就…

python爬虫-多线程-数据库——WB用户

数据库database的包&#xff1a; Python操作Mysql数据库-CSDN博客 效果&#xff1a; 控制台输出&#xff1a; 数据库记录&#xff1a; 全部代码&#xff1a; import json import os import threading import tracebackimport requests import urllib.request from utils im…

博客文章质量分数列表【分页、排序、搜索】

文章目录 一、分析二、代码1、前端代码2、后端代码 三、实现效果四、总结1、出现安全验证2、401 Unauthorized: [no body] 一、分析 官方提供的质量分查询入口&#xff1a;CSDN质量分 输入我们要查的文章即可&#xff0c;比如&#xff1a;https://blog.csdn.net/qq_36433289/a…

开发板——X210开发板的SD卡启动方式

以下内容源于朱有鹏嵌入式课程的学习与整理&#xff0c;如有侵权请告知删除。 参考博客&#xff1a; S5PV210 SD卡启动 - 简书 关于存储器的相关基础知识&#xff0c;见博文&#xff1a; 外存——SD卡/iNand芯片与S5PV210的SD/MMC/iNand控制器-CSDN博客 RAM、ROM和FLASH三…

了解WPF控件:TreeView常用属性与用法(十五)

引言 TreeView控件是WPF&#xff08;Windows Presentation Foundation&#xff09;中用于显示分层数据的常用控件。这个控件允许用户以树形结构展示数据&#xff0c;使得数据更加清晰易懂。在创建文件浏览器、组织结构图等应用程序时&#xff0c;TreeView控件非常有用。 Tree…

R语言入门笔记2.0

1.创建数据框 在R语言中&#xff0c;可以使用data.frame函数来创建数据框。以下是一个简单的示例&#xff0c;这段R语言代码创建了一个名为student的数据框&#xff0c;其中包含了学生的ID、性别、姓名和出生日期&#xff0c;首先创建一个包含学生出生日期的向量&#xff0c;再…

探秘本庄村果园预售系统的技术之旅

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

【MCAL】TC397+EB-tresos之GPT配置实战 - 定时器

本篇文章介绍了在TC397平台使用EB-tresos对GPT驱动模块进行配置的实战过程,不仅介绍了使用GTM来实现定时器的方案&#xff0c;还介绍了基于GPT12来实现连续定时器的实例。因为GTM是德国博世公司开发的IP&#xff0c;而英飞凌的芯片集成了这个IP&#xff0c;并在这个基础上搭建了…

Pytest 与allure测试报告集成

通过Feature, story, step 记录测试的功能&#xff0c;场景及测试步骤 # login.pylogin_func函数 传入参数是name 和 password 当输入的name和password与数据库db_data中数据一致时&#xff0c;返回“XXX成功登录系统&#xff01;” 当输入的name存在于数据库db_data但密码不正…

双非本科准备秋招(13.1)—— 力扣 栈、队列与堆

1、103. 二叉树的锯齿形层序遍历 昨天做的二叉树的层序遍历&#xff0c;把代码直接拿过来。 这个题要求的是一个Z型遍历&#xff0c;如下图。 用一个变量f记录正反顺序&#xff0c;然后使用LinkedList记录答案&#xff0c;下图可以看到LinkedList继承了Deque&#xff0c;所以…

【知识图谱--第一讲概论】

深度学习–连接主义 知识图谱–符号主义 表示 有属性图和RDF图两种 RDF由三元组表示&#xff1a;Subject - Predicate - Object 存储 图数据库 抽取 融合 推理 问答 图算法

Linux:进程信号的概念与产生原理

文章目录 信号的概念实践信号关于前台和后台进程的操作 操作系统与外设信号的产生signal系统调用 前面的篇章结束了信号量的话题&#xff0c;那么接下来引入的是信号的话题&#xff0c;信号和信号量之间没有任何关系&#xff0c;只是名字比较像 信号的概念 在生活中存在各种各…

linux麒麟系统安装mongodb7.0

1.mogedb下载 下载的是他tar包 https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-7.0.5.tgz wget -o https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel80-7.0.5.tgz 也可以下载rpm包 2.将包上传至服务器并解压 #进入目录 并解压 cd /opt/ tar…