【二叉树】【动态规划】1、斐波那契数+2、零钱兑换

1、遍历:在遍历的过程中就能够解决问题,只需要递归函数的参数即可。
2、子树:只有在遍历完成之后才能解决问题,还需要递归函数的返回值。(需要在后序位置写代码)

动态规划:子树 核心思想是穷举求最值
动态规划三要素:

正确的状态转移方程
具有最优子结构
存在重叠子问题(暴力穷举效率很低,需要使用备忘录(dp table)来优化穷举过程)

明确状态,明确选择,定义dp数组
回溯算法:树枝
DFS算法:节点

1、斐波那契数(难度:简单)

在这里插入图片描述

该题对应力扣网址

AC方法和对应代码

1、暴力递归穷举
重复计算太多
时间复杂度是O(2的n次方)

class Solution {
public://暴力递归穷举int fib(int n) {if(n==0 || n==1){return n;}return fib(n-1)+fib(n-2);}
};

2、带备忘录的递归解法
使用备忘录数组或者字典(这里用的数组)来记录每次已经算过的fib(n),避免重复计算
时间复杂度是O(n)

class Solution {
public://带备忘录的递归解法int fib(int n) {int nums[n+1];memset(nums,-1,sizeof(nums));return dp(nums, n);}int dp(int nums[], int n){if(n==0 || n==1){nums[n]=n;}//备忘录if(nums[n]!=-1){return nums[n];}return dp(nums,n-1)+dp(nums,n-2);}
};

3、dp数组的迭代(递推)解法(for循环)
前面两种方法都是自顶向下,然后最后通过返回值将答案返回给上级,本质上是自顶向下的思路。
这种方法是自底向上,仍然使用备忘录(数组)来辅助完成推算。
(注意:声明一个n+2的数组int dp[n+2],因为dp[0]=0,dp[1]=1,当n<2的时候,不这么定义会出现数组下标溢出的情况。)

class Solution {
public:int fib(int n) {int dp[n+2];dp[0]=0;dp[1]=1;for(int i=2;i<=n;i++){dp[i]=dp[i-1]+dp[i-2];}return dp[n];}
};

以上斐波那契数的题目也不算严格意义上的动态规划题目,只因为涉及到重叠子问题的消除。

暴力解的优化方法是用备忘录或者dp table
斐波那契数还有优化方法,可以将时间复杂度降为o(1)
把dp table的大小从n缩小到n

2、零钱兑换(难度:中等)

(看不懂啊看不懂,狗头保命)
在这里插入图片描述
该题对应力扣网址

动态规划递归模板

# 自顶向下递归的动态规划
def dp(状态1, 状态2, ...):for 选择 in 所有可能的选择:# 此时的状态已经因为做了选择而改变result = 求最值(result, dp(状态1, 状态2, ...))return result

动态规划迭代模板

# 自底向上迭代的动态规划
# 初始化 base case
dp[0][0][...] = base case
# 进行状态转移
for 状态1 in 状态1的所有取值:for 状态2 in 状态2的所有取值:for ...dp[状态1][状态2][...] = 求最值(选择1,选择2...)

超出时间限制

由于重复计算,导致超时严重。。

class Solution {
public:int coinChange(vector<int>& coins, int amount) {return dp(coins,amount);}//状态是amount,即本题中的变量//选择:能够使状态发生变化,本题中指的是不同面值的硬币及个数//dp函数,函数参数包含状态,函数返回值是题目需要计算的值int dp(vector<int>& coins, int amount){if(amount==0){return 0;}if(amount<0){return -1;}int res=INT_MAX;//对所有可能的选择for(int coin: coins){int subsum=dp(coins,amount-coin);if(subsum==-1)continue;res=min(res,subsum+1);}return res==INT_MAX?-1:res;}
};

AC代码(递归+备忘录)

设置一个dp数组来作为备忘录
写的时候出现了两个问题:
1、备忘录数组的初始化问题,memset(memo,-1,sizeof(memo))用这个初始化方法初始化后不对~~(原理我之后再补)~~
2、一开始加上备忘录之后还是超时,后来发现备忘录数组其实和最后的res是一个值,所以应该放在返回值的地方再确定备忘录数组的值。

class Solution {
public:int coinChange(vector<int>& coins, int amount) {//定义一个备忘录// int memo[amount+1]={-2};int* memo = new int[amount + 1];for (int i = 0; i <= amount; ++i) {memo[i] = -2;}// memset(memo,-1,sizeof(memo));// cout<<"尺寸:"<<sizeof(memo)<<endl;// cout<<"初始化:"<<memo[0]<<endl;return dp(memo,coins,amount);}//int dp(int memo[], vector<int>& coins, int amount){if(amount==0){return 0;}if(amount<0){return -1;}if(memo[amount]!=-2){return memo[amount];}int subsum;int res=INT_MAX;for(int coin: coins){// if(amount-coin>=0 && memo[amount-coin]!=-2){//     res=memo[amount-coin];// }subsum=dp(memo,coins,amount-coin);if(subsum==-1)continue;res=min(res,subsum+1);}if(res==INT_MAX){res=-1;}memo[amount]=res;return res;}
};

AC代码(迭代+dp数组)

看完题解了解完主要思路之后,终于把这个代码复现下来了,发现代入具体例子之后,才懂了在什么地方求最小值等等。
做的时候有个地方,就是int+int超出了数据范围报错,于是改成了相减amount-i-coin,解决了超限问题。

class Solution {
public:int coinChange(vector<int>& coins, int amount) {//迭代+dp数组int *dp = new int[amount+1];//base case dp[0]for(int j=1;j<=amount;j++){dp[j]=-1;}dp[0]=0;int res=INT_MAX;//进行状态转移//循环所有的状态1,原递归的参数for(int i=0;i<=amount;i++){//循环所有状态2for(int coin:coins){if(dp[i]==-1)continue;res=dp[i]+1;if((amount-i-coin)<0)continue;if(dp[i+coin]!=-1){dp[i+coin]=min(res,dp[i+coin]);}else{dp[i+coin]=res;}//dp[1]=dp[0]+1=1//dp[2]=dp[0]+1=1//dp[5]=dp[0]+1=1//dp[1+1]=dp[2]=dp[1]+1=2//dp[1+2]=dp[3]=dp[1]+1=2//dp[1+5]=dp[6]=dp[1]+1=2//dp[2+1]=dp[3]=dp[2]+1=3//dp[2+2]=dp[4]=dp[2]+1=3//dp[2+5]=dp[7]=dp[2]+1=3//...//dp[6+5]=dp[6]+1=3//例如://dp[2]=1=2}}return dp[amount];}
};

从二叉树过来的,听说二叉树的思路可以延伸出来动态规划和回溯等算法,动态规划看了好几天的讲解,现在还是迷糊,费老大劲根据题解写完了两道题,总算有点思路了。

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

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

相关文章

Leetcode 3217. Delete Nodes From Linked List Present in Array

Leetcode 3217. Delete Nodes From Linked List Present in Array 1. 解题思路2. 代码实现 题目链接&#xff1a;3217. Delete Nodes From Linked List Present in Array 1. 解题思路 这一题是一个十分典型的链表的问题&#xff0c;我们注意区分一下头节点和中间节点即可。 …

【electron】 快速启动electron 应用

学无止境&#xff1a; 最近在搞electron项目&#xff0c;最重要的是总结 &#xff0c;写下来总不会忘记&#xff0c;也希望给大家参考一下&#xff0c;有不对的地方希望大家多指点。 快速启动electron 应用 1 克隆示例项目的仓库 git clone https://github.com/electron/ele…

【Oracle】Oracle中的LISTAGG函数

目录 解释与其他聚合函数的区别 使用场景语法分析函数用法聚合函数用法对比 示例分析函数使用案例聚合函数使用案例 优缺点LISTAGG函数的优点&#xff1a;LISTAGG函数的缺点&#xff1a; 注意事项 解释 LISTAGG函数是一种用于字符串连接的聚合函数&#xff0c;可以将多行的值进…

基于最新版的flutter pointycastle: ^3.9.1的AES加密

基于最新版的flutter pointycastle: ^3.9.1的AES加密 自己添加pointycastle: ^3.9.1库config.dartaes_encrypt.dart 自己添加pointycastle: ^3.9.1库 config.dart import dart:convert; import dart:typed_data;class Config {static String password 成都推理计算科技; // …

Hadoop-36 HBase 3节点云服务器集群 HBase Shell 增删改查 全程多图详细 列族 row key value filter

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 目前已经更新到了&#xff1a; HadoopHDFSMapReduceHiveFlumeSqoopZookeeperHBase 正在 章节内容 上一节我们完成了&#xff1a; 集群的…

从安装Node到TypeScript到VsCode的配置教程

从安装Node到TypeScript到VsCode的配置教程 1.下载Node安装包&#xff0c; 链接 2.双击安装包&#xff0c;选择安装路径&#xff0c;如下&#xff1a; 3.一直点击下一步&#xff0c;直至安装结束即可&#xff1a; 这个时候&#xff0c;node会默认配置好环境变量&#xff0c;并且…

java文本比较解决方案

参考资料 VBA计算页码和行号https://learn.microsoft.com/zh-cn/office/vba/api/word.wdinformation 概述&#xff1a; 最近在做word文档对比的&#xff0c;总结了几种解决方案&#xff0c;记录一下 在java中&#xff0c;常用的文本对比方案有如下几种&#xff1a; 差异比较…

Golang 创建 Excel 文件

经常会遇到需要导出数据报表的需求&#xff0c;除了可以通过 encoding/csv 导出 CSV 以外&#xff0c;还可以使用 https://github.com/qax-os/excelize 导出 xlsx 等格式的 excel&#xff0c;下面封装了一个方法&#xff0c;支持多 sheet 的 excel 数据生成&#xff0c;导出按需…

Linux网络——套接字与UdpServer

目录 一、socket 编程接口 1.1 sockaddr 结构 1.2 socket 常见API 二、封装 InetAddr 三、网络字节序 四、封装通用 UdpServer 服务端 4.1 整体框架 4.2 类的初始化 4.2.1 socket 4.2.2 bind 4.2.3 创建流式套接字 4.2.4 填充结构体 4.3 服务器的运行 4.3.1 rec…

Windows 使用 MinGW 编译 OpenCV

使用 MinGW 编译 OpenCV 是一个不错的选择&#xff0c;特别是如果您想避免使用 Visual Studio。下面是使用 MinGW 和 CMake 编译 OpenCV 的详细步骤。 准备工作 1. 下载 OpenCV 源代码 从 OpenCV GitHub 仓库下载 OpenCV 源代码。 git clone https://github.com/opencv/ope…

rabbitmq生产与消费

一、rabbitmq发送消息 一、简单模式 概述 一个生产者一个消费者模型 代码 //没有交换机&#xff0c;两个参数为routingKey和消息内容 rabbitTemplate.convertAndSend("test1_Queue","haha");二、工作队列模式 概述 一个生产者&#xff0c;多个消费者&a…

如何将PDF转换成可以直接编辑的CAD图纸?

PDF图纸是为了让用户更好的阅览CAD文件&#xff0c;但是&#xff0c;当我们想要对其进行编辑的时候&#xff0c;PDF图纸就是一个麻烦了。那么PDF转换成CAD后可以编辑吗&#xff1f;如何将PDF转换成可以直接编辑的CAD图纸呢&#xff1f;本篇给你答案。 1、启动迅捷CAD编辑器&…

easyui 列表展示 如何解析 ResponseEntity<Page<Monthlycoefficient>> 这样的返回结构

在使用 EasyUI 展示列表数据时&#xff0c;通常需要将后端返回的数据解析为 EasyUI 数据网格&#xff08;datagrid&#xff09;所需的格式。假设你的后端返回的是一个 ​​ResponseEntity<Page<MonthlyCoefficient>>​​​ 结构&#xff0c;其中 ​​Page​​​ 是…

【python学习】爬虫中常使用的urllib和requests库的的背景、定义、特点、功能、代码示例以及两者的区别

引言 urllib是Python标准库中的一个模块&#xff0c;它提供了一系列用于操作URL的功能 requests是一个Python第三方库&#xff0c;由Kenneth Reitz创建&#xff0c;用于简化HTTP客户端的编程 一、urllib的定义 urllib可以操作url&#xff0c;主要分为以下几个子模块&#xff1…

从人工巡检到智能防控:智慧油气田安全生产的新视角

一、背景需求 随着科技的飞速发展&#xff0c;视频监控技术已成为各行各业保障安全生产、提升管理效率的重要手段。特别是在油气田这一特殊领域&#xff0c;由于其工作环境复杂、安全风险高&#xff0c;传统的监控方式已难以满足实际需求。因此&#xff0c;基于视频监控AI智能…

侧开知识点合集2

一、try .... catch.. AccessViolationException异常触发后&#xff0c;下列程序的输出结果为 static void Main(string[] args) { try { throw new AccessViolationException(); Console.WriteLine("error1"); } catch (Exception e) { Console.WriteLi…

ROS2从入门到精通2-3:机器人3D物理仿真Gazebo与案例分析

目录 0 专栏介绍1 什么是Gazebo&#xff1f;2 Gazebo架构2.1 Gazebo前后端2.2 Gazebo文件格式2.3 Gazebo环境变量 3 Gazebo安装与基本界面4 搭建自己的地图4.1 编辑地图4.2 保存地图4.3 加载地图 5 常见问题 0 专栏介绍 本专栏旨在通过对ROS2的系统学习&#xff0c;掌握ROS2底…

CSS技巧专栏:一日一例 8 - 纯CSS利用mask属性实现按钮边框对称包围特效

CSS技巧专栏:一日一例 8 - 纯CSS利用mask属性实现按钮边框对称包围特效 上篇作业解题 在前一篇文章的最后,给各位看官留了一个作业,如上图所示。本篇文章,我们来公布一下它的源码。 主要实现的思路 四个渐变色的线段,沿着四个方向的依次运动,(运动在加载前执行)使用 …

均值滤波算法及实现

均值滤波器的使用场景&#xff1a; 均值滤波器使用于处理一些如上述蓝色线的高斯噪声场景 红色曲线是经过均值滤波处理后的数据。主要因为均值滤波设置数据缓冲区&#xff08;也即延时周期&#xff09;&#xff0c;使得测量值经过缓冲不会出现特别大的变化。 黄色曲线为高斯噪声…

【iOS】—— 消息传递和消息转发

【iOS】—— 消息传递和消息转发 1. 消息传递SEL选择子IMP快速查找汇编代码查找过程总结消息转送快速查找IMP 慢速查找总结消息传递慢速查找IMP 2. 消息转发动态决议动态解析添加方法 快速转发慢速转发 总结动态决议消息转发消息的三次拯救 1. 消息传递 在iOS中&#xff0c;消…