算法学习笔记Day9——动态规划基础篇

一、介绍

本文解决几个问题:动态规划是什么?解决动态规划问题有什么技巧?如何学习动态规划?

1. 动态规划问题的一般形式就是求最值。动态规划其实是运筹学的一种最优化方法,只不过在计算机问题上应用比较多,比如说让你求最长递增子序列呀,最小编辑距离呀等等。

2. 动态规划的核心思想就是穷举求最值,但只有列出正确的「状态转移方程」,才能正确地穷举。你需要判断算法问题是否具备「最优子结构」,是否能够通过子问题的最值得到原问题的最值。另外,动态规划问题存在「重叠子问题」,如果暴力穷举的话效率会很低,所以需要你使用「备忘录」或者「DP table」来优化穷举过程,避免不必要的计算。

以上提到的重叠子问题、最优子结构、状态转移方程就是动态规划三要素。

3. 思维框架:明确 base case -> 明确「状态」-> 明确「选择」 -> 定义 dp 数组/函数的含义

递归是自顶向下,动态规划是自底向上

4. 带备忘录的递归和动态规划实际上是等价的,动态规划是从底层开始,一步一步完成对数组的完善,所以不需要备忘录,或者说dp数组本身就是备忘录,递归会遇到很多重复的子问题,所以需要备忘录来简化。

二、例题

例题1:斐波那契数

分析

写出状态转移方程,写出基底,就可以开始自底向上构造了。

代码

思路1:自底向上解法

class Solution {
public:int fib(int n) {if(n == 0 || n == 1){return n;}int fib_1 = 1, fib_2 = 0;int fib_i;for(int i = 2; i<= n; i++){fib_i = fib_1 + fib_2;fib_2 = fib_1;fib_1 = fib_i;}return fib_i;}
};

思路2:自顶向下解法

class Solution {
public:vector<int> diary;int recursion(int n){//基地if(n == 0 || n == 1){return n;}//查日记if(diary[n] != -1){return diary[n];}//日记没查到,更新日记,用递归更新它diary[n] = recursion(n-1) + recursion(n-2);//再查找日记本return diary[n];}int fib(int n) {diary.resize(n+1, -1);return recursion(n);}
};

例题2:零钱兑换

分析

写出状态方程就可以了

代码

思路1:带备忘录的递归

class Solution {
public:vector<int> diary;int dp(vector<int>& coins, int amount){if(amount < 0){return -1;}if(amount == 0){return 0;}if(diary[amount] != 0){return diary[amount];}int ans = INT_MAX;for(int coin : coins){int subsolution = dp(coins, amount - coin);if(subsolution != -1){ans = min(subsolution+1, ans);}}diary[amount] = ans==INT_MAX ? -1:ans;return diary[amount];}int coinChange(vector<int>& coins, int amount) {diary.resize(amount+1, 0);return dp(coins, amount);}
};

不知道为什么把diary初始化为-1就会超时,推测是-1表示不可能的情况,有很多正数diary也是-1,就容易进入循环,但是0只有0这个情况。

思路2:dp迭代

class Solution {
public:int coinChange(vector<int>& coins, int amount) {vector<int> dp(amount + 1, INT_MAX-1);//base situationdp[0] = 0;for(int i  =0; i<=amount; i++){for(int coin : coins){if(i - coin < 0){continue;}dp[i] = min(dp[i], dp[i-coin] + 1);}}return dp[amount]==INT_MAX-1?-1:dp[amount];}
};

例题3:最长递增子序列

分析

首先要明确dp数组代表什么,这里是以 位置i数字 结尾的最长字序列长度,对于每个位置,比较前面的位置,只要它大于某个元素,就可以和那个元素的最长子序列组成新的最长子序列。

代码

class Solution {
public:int lengthOfLIS(vector<int>& nums) {vector<int> dp(nums.size(), 1);for(int i  = 0; i< nums.size(); i++){for(int j = 0; j<i; j++){if(nums[i] > nums[j])dp[i] = max(dp[i], dp[j] + 1);}}return *max_element(dp.begin(), dp.end());}
};

例题4:俄罗斯套娃信封问题 

代码

class Solution {
public:int maxEnvelopes(vector<vector<int>>& envelopes) {int n = envelopes.size();sort(envelopes.begin(), envelopes.end(), [](vector<int>& a, vector<int>& b)->bool{return a[0] == b[0]? a[1] > b[1] : a[0] < b[0];});vector<int> dp(n, 1);for(int i = 0; i<n; i++){for(int j = 0; j< i; j++){if(envelopes[i][1] > envelopes[j][1]){dp[i] = max(dp[i], dp[j] + 1);}}}return *max_element(dp.begin(), dp.end());}
};

三、总结

i)斐波那契数列的问题,解释了如何通过「备忘录」或者「dp table」的方法来优化递归树,并且明确了这两种方法本质上是一样的,只是自顶向下和自底向上的不同而已。

ii)凑零钱的问题,展示了如何流程化确定「状态转移方程」,只要通过状态转移方程写出暴力递归解,剩下的也就是优化递归树,消除重叠子问题而已。

iii)二维数组也可以排序,要传入一个lamda表达式来说明排序的方式,第四题套娃问题,同样长的信封必须按宽的逆序排列,因为同样大小是不可以嵌套的,如果顺序排列,求最长递增子序列的时候就会多一个。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kotlin 编写一个简单的天气预报app (七)使用material design

一、优化思路 对之前的天气预报的app进行了优化&#xff0c;原先的天气预报程序逻辑是这样的。 使用text和button组合了一个输入城市&#xff0c;并请求openweathermap对应数据&#xff0c;并显示的功能。 但是搜索城市的时候&#xff0c;可能会有错误&#xff0c;比如大小写…

超市火灾烟雾蔓延及人员疏散的matlab模拟仿真,带GUI界面

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 出口在人员的视野范围内时&#xff0c;该元胞选择朝向引导点的方向运动。出口不在人员的视野范围内时&#xff0c;作随机运动&#xff0c;8个方向的运动概率相等。…

深度学习| 注意力机制

注意力机制 为什么需要注意力机制Seq2Seq问题Transfomer Attention注意力机制分类软硬注意力注意力域 为什么需要注意力机制 这个可以从NLP的Seq2Seq问题来慢慢理解。 Seq2Seq问题 Seq2Seq&#xff08;Sequence to Sequence&#xff09;&#xff1a;早期很多模型中&#xff…

清除git缓存后,每次pull或者push都需要输入用户名密码

git bash进入你的项目目录&#xff0c;输入&#xff1a;git config --global credential.helper store 然后在文件下pull一下&#xff0c;输入一次用户名密码后&#xff0c;再次pull或者push就不需要输入了。 亲测有用哦

挑战一周完成Vue3项目Day2:路由配置+登录模块+layout组件+路由鉴权

一、路由配置 经过分析&#xff0c;项目一共需要4个一级路由&#xff1a;登录&#xff08;login&#xff09;、主页&#xff08;home&#xff09;、404、任意路由&#xff08;重定向到404&#xff09;。 1、安装路由插件 pnpm install vue-router 2、创建路由组件 在src目…

区块链安全应用-------压力测试

基于已有的链进行测试&#xff08;build_chain默认建的链 四个节 点&#xff09;&#xff1a; 第一步&#xff1a;搭链 1. 安装依赖 在ubuntu操作系统中&#xff0c;操作步骤如下&#xff1a; sudo apt install -y openssl curl 2. 创建操作目录, 下载安装脚本 ## 创建操作…

Selenium web自动化测试环境搭建

Selenium web自动化环境搭建主要要经历以下几个步骤&#xff1a; 1、安装python 在python官网&#xff1a;Welcome to Python.org&#xff0c;根据各自对应平台如&#xff1a;windows&#xff0c;下载相应的python版本。 ​ 下载成功后&#xff0c;点击安装包&#xff0c;一直…

CMakeLists.txt中如何添加编译选项?

1. 引子 编译器有多种可供选择&#xff0c;如g、c、clang等&#xff0c;如下以c作为示例。 2. 使用CMAKE_CXX_FLAGS添加编译选项 在Makefile中可能用类似如下的指令来添加编译选项&#xff1a; /usr/bin/c -Wall -Wextra -Wno-sign-compare -Wno-unused-variable -Wno-unuse…

【Node.js】02 —— Path模块全解析

&#x1f31f;Node.js之Path模块探索&#x1f308; &#x1f4da;引言 在Node.js的世界中&#xff0c;path模块就像一把万能钥匙&#x1f511;&#xff0c;它帮助我们理解和操作文件与目录的路径。无论你是初入Node.js殿堂的新手&#xff0c;还是久经沙场的老兵&#xff0c;理…

什么样的内外网文档摆渡,可以实现安全高效传输?

内外网文档摆渡通常指的是在内网&#xff08;公司或组织的内部网络&#xff09;和外网&#xff08;如互联网&#xff09;之间安全地传输文件的过程。这个过程需要特别注意安全性&#xff0c;因为内网往往包含敏感数据&#xff0c;直接连接内网和外网可能会带来安全风险。因此会…

git 命令怎么回退到指定的某个提交 commit hash 并推送远程分支?

问题 如下图&#xff0c;我要回退到 【002】Babel 的编译流程 这一次提交 解决 1、先执行下面命令&#xff0c;输出日志&#xff0c;主要就是拿到提交 commit 的 hash&#xff0c;上图红框即可 git log或者 vscode 里面直接右击&#xff0c;copy sha 2、执行下面命令回退 g…

Flask 数据库前后端交互案例-1

Flask 数据库前后端交互案例 目录结构templates目录base.htmlheader.htmlleft.html首页职员管理页面添加员工界面员工编辑页面员工详情界面 后台main.pyapp.pymodels.pyviews.py 数据库数据position.sqlperson.sqlpermission.sqldepartment.sql 目录结构 静态文件链接&#xff…

ArcGIS Pro 和 Python — 分析全球主要城市中心的土地覆盖变化

第一步——设置工作环境 1–0. 地理数据库 在下载任何数据之前,我将创建几个地理数据库,在其中保存和存储所有数据以及我将创建的后续图层。将为我要分析的五个城市中的每一个创建一个地理数据库,并将其命名为: “Phoenix.gdb” “Singapore.gdb” “Berlin.gdb” “B…

Git--分布式版本控制系统

目录 一、理解分布式版本控制系统二、远程仓库三、克隆远程仓库四、向远程仓库推送五、拉取远程仓库六、配置Git七、给命令配置别名八、创建标签九、操作标签 一、理解分布式版本控制系统 我们⽬前所说的所有内容&#xff08;⼯作区&#xff0c;暂存区&#xff0c;版本库等等&a…

AI文章写作网站

最强AI文章写作网站——心语流光&#xff08; Super Ai Writer &#xff09; 特点 多轮问答写作&#xff0c;自动携带历史记录进行问答可以自定义携带历史记录的轮数&#xff0c;为0则携带全部历史记录&#xff0c;有效避免token浪费&#xff08;类似coze平台&#xff09;AI生…

探讨mfc100u.dll丢失的解决方法,修复mfc100u.dll有效方法解析

mfc100u.dll丢失是一个比较常见的情况&#xff0c;由于你电脑的各种操作&#xff0c;是有可能引起dll文件的缺失的&#xff0c;而mfc100u.dll就是其中的一个重要的dll文件&#xff0c;它的确实严重的话是会导致程序打不开&#xff0c;系统错误的。今天我们就来给大家科普一下mf…

Python爬虫--Ajax异步抓取腾讯视频评论

在某些网站 &#xff0c;当我们滑下去的时候才会显示出后面的内容 就像淘宝一样&#xff0c;滑下去才逐渐显示其他商品 这个就是采用 Ajax 做的 然后我们现在就是要编写这样的爬虫。 规律分析&#xff1a; 这个时候就要用到我们的 Fiddler 了 我们需要分析加载评论的规律 …

【Linux】NFS网络文件系统搭建

一、服务端配置 #软件包安装 [roothadoop01 ~]# yum install rpcbind nfs-utils.x86_64 -y [roothadoop01 ~]# mkdir /share#配置文件修改 #格式为 共享资源路径 [主机地址] [选项] # [roothadoop01 ~]# vi /etc/exports /share 192.168.10.0/24(rw,sync,no_root_squash) #…

Wi-Fi HaLow:重塑物联网的未来

Wi-Fi HaLow&#xff1a;引领物联网连接的革命 数字时代的蓬勃发展正在引发一场深刻的变革&#xff0c;物联网已经融入到我们的日常生活和工作中&#xff0c;成为不可或缺的一部分。随着新一代Wi-Fi技术一Wi-Fi HaLow的崭露头角&#xff0c;有望在2024年及未来&#xff0c;重新…