算法学习笔记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.mzph.cn/diannao/4371.shtml

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

相关文章

opencv_17_翻转与旋转

一、图像翻转 1&#xff09;void flip_test(Mat& image); 2&#xff09;void ColorInvert::flip_test(Mat& image) { Mat dst; //flip(image, dst, 0); //上下翻转 flip(image, dst, 1); //左右翻转 // flip(image, dst, -1); //180度翻转 imsho…

OpenVINO安装教程 vcpkg版

通过 vcpkg 安装 OpenVINO™ Runtime 请注意&#xff0c;vcpkg 发行版&#xff1a; 仅提供 C/C API 不支持 NPU 推理 专用于所有主要操作系统的用户&#xff1a;Windows、Linux 和 macOS &#xff08;所有 x86_64 / ARM64 架构&#xff09; 系统要求处理器说明软件要求 完整…

B站美化插件,支持自定义,太酷辣~

大公司的软件和网站通常具有优雅的默认界面设计。 以国内二次元聚集地B站为例&#xff0c;可以说它的UI设计非常吸引人。与其他视频网站繁复的设计相比&#xff0c;B站的界面设计可以说是遥遥领先 然而&#xff0c;总有些人对默认的用户界面感到不满意&#xff0c;他们渴望尝试…

接口自动化测试框架

接口自动化测试框架&#xff1a;pythonunittest/pytestrequestsddtopenpyxlpymysqllogging 框架设计思路数据驱动结构分层&#xff08;可读性、可维护性、可扩展性&#xff09;数据驱动将维护数据与代码分离&#xff0c;接口调用行为一致&#xff0c;针对不同的参数组合驱动不同…

fiddler提示“The system proxy was changed.Click to reenable capturing.”的原因及解决办法

一、现象描述 运行fiddler时&#xff0c;提示“The system proxy was changed.Click to reenable capturing.”&#xff0c;即使点击了该提示&#xff0c;重新进行抓包&#xff0c;不一会儿&#xff0c;该提示又会出现&#xff0c;又不能进行抓包了。 二、解决方法 2.1 原因一&…

Java 高级面试问题及答案

Java 高级面试问题及答案 问题 1: 在 Java 中&#xff0c;什么是强引用、软引用、弱引用和虚引用&#xff1f;它们分别有什么用途&#xff1f; 探讨过程&#xff1a; 在Java中&#xff0c;对象的引用类型决定了垃圾回收器如何回收对象。强引用是最常见的&#xff0c;它阻止垃…

java 根据对象的boolean字段对集合进行排序

java 根据对象的boolean字段对集合进行排序 ‍ 需求大概如下&#xff1a; 把boolean为true的排序到前面,false排序到后面 ‍ 排序后, boolean为true的会在前面, 为false的会在后面 , isHasMaterial 为boolean类型 Data Builder public class MoguPoiBaseInfo {/*** 是否有…

输电线路的“天眼”:双目协同图像视频监测装置

在广袤的天地之间&#xff0c;纵横交错的输电线路如同血脉一般&#xff0c;为我们的生活输送着源源不断的电力。然而&#xff0c;这些“血脉”也常常面临着各种挑战&#xff0c;如外力破坏、恶劣天气等。为了守护这些重要的“生命线”&#xff0c;鼎信智慧研发了一款智能监控设…

LeetCode 1146. 快照数组【哈希表+二分查找】中等

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

云原生Kubernetes: K8S 1.29版本 部署GitLab

目录 一、实验 1.环境 2.搭建NFS 3.K8S 1.29版本 部署Redis 4.K8S 1.29版本 部署Postgresql 5.K8S 1.29版本 部署GitLab 6.K8S 部署istio微服务 7.K8S 部署ingress应用路由 二、问题 1.K8S部署gitlab报错 2.gitlab创建失败 3.生成网关资源报错 4.安装istio 报错 …

APP自定义身份证相机(Android +iOS)

基本上同时兼容安卓和苹果的插件都需要付费&#xff0c;这里我找了2个好用的免费插件 1.仅支持安卓&#xff1a;自定义身份证相机&#xff08;支持蒙版自定义&#xff09;&#xff0c;内置蒙版&#xff0c;照片预览&#xff0c;身份证裁剪 - DCloud 插件市场、 2.支持iOS(已测…

打水问题(贪心算法)

题目&#xff1a;有n个人排队到r个水龙头去打水&#xff0c;他们装满水桶的时间t1、t2………tn为整数且各不相等&#xff0c;应如何安排他们的打水顺序才能使他们总共花费的时间最少&#xff1f;通过键盘输入排队打水的人数以及每人打水的时间和水龙头数&#xff0c;使用贪心算…

泰迪智能科技受邀参加2024年粤港澳大湾区产教融合技能人才培养联盟理事会会议

4月24日下午&#xff0c;2024年粤港澳大湾区产教融合技能人才培养联盟&#xff08;以下简称联盟&#xff09;理事会会议在白云区成功举办。 会议由广州市人力资源和社会保障局、广州市发展和改革委员会、广州市教育局、广州市工业和信息化局、广州市总工会等单位指导&#xff…

Python实现对规整的二维列表中每个子列表对应的值求和

目录 一、二维列表及其结构 二、对应位置元素求和的逻辑 三、代码实现 四、优化与改进 五、实际应用场景 六、扩展与变体 七、总结 在Python编程中&#xff0c;处理二维列表&#xff08;即列表的列表&#xff09;是一个常见的任务。有时候我们需要对二维列表中每个子列表…

多线程编程7——wait和notify、notifyAll

线程最大的问题就是抢占式执行&#xff0c;随机调度。可以通过一些API让线程主动阻塞&#xff0c;主动放弃CPU&#xff0c;从而控制线程之间的执行顺序。比如&#xff1a;join&#xff0c;sleep&#xff0c;wait和notify、notifyAll 前面章节已经介绍过 join 和 sleep了&#…

计算机网络-IPv6地址规范与分类

昨天学习了IPv6的基础概念&#xff0c;了解了IPv6的由来以及地址格式&#xff0c;今天继续学习下IPv6的地址分类与表示。 一、IPv6地址缩写规范 IPv6地址的长度为128 bit。一般用冒号分割为8段&#xff0c;每一段16 bit&#xff0c;每一段内用十六进制表示。 IPv6地址格式 那12…

3-成功初始化 Kubernetes 控制平面后如何操作

成功初始化 Kubernetes 控制平面后的一系列指示和建议&#xff0c;用于帮助你开始使用你的 Kubernetes 集群。下面是详细的解释和步骤&#xff1a; kubeadm init --apiserver-advertise-address 172.19.35.202 --image-repository registry.cn-hangzhou.aliyuncs.com/google_c…

MATLAB 基础使用教程

MATLAB 的基本使用主要包括如下几个方面&#xff1a;熟悉 MATLAB 环境&#xff0c;数据的输入输出&#xff0c;基本的数学运算&#xff0c;图形绘制&#xff0c;编程等。以下通过一些例子进行简要说明。 1. 熟悉 MATLAB 环境 启动 MATLAB 后&#xff0c;你会看到 MATLAB 的桌面…

【kettle004】kettle访问本地MySQL数据库并处理数据至execl文件

一直以来想写下基于kettle的系列文章&#xff0c;作为较火的数据ETL工具&#xff0c;也是日常项目开发中常用的一款工具&#xff0c;最近刚好挤时间梳理、总结下这块儿的知识体系。 熟悉、梳理、总结下MySQL关系数据库相关知识体系 kettle访问MySQL数据库并处理数据至execl文件…

Linux 权限提升 - 信息收集 清单

这个清单主要使用于内网渗透的其中一个环节&#xff0c;信息收集此环节涉及后续是否有高效的攻击成绩&#xff0c;通过某些手段和技巧&#xff0c;可获取更多的彩蛋&#xff01;&#x1f386; 攻击者可以发现目标系统的弱点和漏洞&#xff0c;包括但不限于&#xff1a; 发现潜…