【算法题】动态规划基础阶段之三步问题、 连续数列、按摩师

news2024/9/25 17:19:04

动态规划基础阶段

  • 前言
  • 一、三步问题
    • 1.1、思路
    • 1.2、代码实现
  • 二、 连续数列
    • 2.1、思路
    • 2.2、代码实现
  • 三、按摩师
    • 3.1、思路
    • 3.2、代码实现
  • 总结

前言

动态规划(Dynamic Programming,简称 DP)是一种解决多阶段决策过程最优化问题的方法。它是一种将复杂问题分解成重叠子问题的策略,通过维护每个子问题的最优解来推导出问题的最优解。

动态规划的主要思想是利用已求解的子问题的最优解来推导出更大问题的最优解,从而避免了重复计算。因此,动态规划通常采用自底向上的方式进行求解,先求解出小规模的问题,然后逐步推导出更大规模的问题,直到求解出整个问题的最优解。

动态规划通常包括以下几个基本步骤:

  1. 定义状态:将问题划分为若干个子问题,并定义状态表示子问题的解;
  2. 定义状态转移方程:根据子问题之间的关系,设计状态转移方程,即如何从已知状态推导出未知状态的计算过程;
  3. 确定初始状态:定义最小的子问题的解;
  4. 自底向上求解:按照状态转移方程,计算出所有状态的最优解;
  5. 根据最优解构造问题的解。

动态规划可以解决许多实际问题,例如最短路径问题、背包问题、最长公共子序列问题、编辑距离问题等。同时,动态规划也是许多其他算法的核心思想,例如分治算法、贪心算法等。

动态规划是一种解决多阶段决策过程最优化问题的方法,它将复杂问题分解成重叠子问题,通过维护每个子问题的最优解来推导出问题的最优解。动态规划包括定义状态、设计状态转移方程、确定初始状态、自底向上求解和构造问题解等步骤。动态规划可以解决许多实际问题,也是其他算法的核心思想之一。

一、三步问题

三步问题。有个小孩正在上楼梯,楼梯有n阶台阶,小孩一次可以上1阶、2阶或3阶。实现一种方法,计算小孩有多少种上楼梯的方式。结果可能很大,你需要对结果模1000000007。

示例1:

输入:n = 3
输出:4
说明: 有四种走法

示例2:

输入:n = 5
输出:13

来源:力扣(LeetCode)。

1.1、思路

三步问题,采用动态规划(思路和上楼梯问题一致),n层楼梯的走法可以分为三种情况:

  1. 剩余一层楼梯要走然后一步走一层。
  2. 剩余两层楼梯要走,然后一步走两层。
  3. 剩余三层楼梯要走,然后一步走三层。

状态方程:
dp[n] = dp[n-1] + dp[n-2] + dp[n-3]

1.2、代码实现

class Solution {
public:
    int waysToStep(int n) {
        if(n==1)
            return 1;
        else if(n==2)
            return 2;
        vector<long> dp(n+1,0);
        dp[1]=1;
        dp[2]=2;
        dp[3]=4;
        for(int i=4;i<=n;i++)
        {
            dp[i]=((dp[i-1]+dp[i-2]+dp[i-3])%1000000007);
        }
        return dp[n];

    }
};

时间复杂度:O(n)。
空间复杂度:O(n)。

二、 连续数列

给定一个整数数组,找出总和最大的连续数列,并返回总和。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

来源:力扣(LeetCode)。

2.1、思路

假设 nums 数组的长度是 n,下标从 0 到 n−1。

我们用 f(i) 代表以第 i 个数结尾的「连续子数组的最大和」,那么很显然我们要求的答案就是:
在这里插入图片描述

因此我们只需要求出每个位置的 f(i),然后返回 f 数组中的最大值即可。那么我们如何求 f(i) 呢?我们可以考虑 nums[i] 单独成为一段还是加入 f(i−1) 对应的那一段,这取决于 nums[i] 和 f(i−1)+nums[i] 的大小,我们希望获得一个比较大的,于是可以写出这样的动态规划转移方程:
f(i)=max{f(i−1)+nums[i],nums[i]}。

不难给出一个时间复杂度 O(n)、空间复杂度 O(n) 的实现,即用一个 f 数组来保存 f(i) 的值,用一个循环求出所有 f(i)。考虑到 f(i) 只和 f(i−1) 相关,于是我们可以只用一个变量 pre 来维护对于当前 f(i) 的 f(i−1) 的值是多少,从而让空间复杂度降低到 O(1),这有点类似「滚动数组」的思想。

2.2、代码实现

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int pre = 0, maxAns = nums[0];
        for (const auto &x: nums) {
            pre = max(pre + x, x);
            maxAns = max(maxAns, pre);
        }
        return maxAns;
    }
};

时间复杂度:O(n),其中 n 为 nums 数组的长度。
空间复杂度:O(1)。我们只需要常数空间存放若干变量。

三、按摩师

一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。

示例 1:

输入: [1,2,3,1]
输出: 4
解释: 选择 1 号预约和 3 号预约,总时长 = 1 + 3 = 4。

示例 2:

输入: [2,7,9,3,1]
输出: 12
解释: 选择 1 号预约、 3 号预约和 5 号预约,总时长 = 2 + 9 + 1 = 12。

示例 3:

输入: [2,1,4,5,3,1,1,3]
输出: 12
解释: 选择 1 号预约、 3 号预约、 5 号预约和 8 号预约,总时长 = 2 + 4 + 3 + 3 = 12。

来源:力扣(LeetCode)。

3.1、思路

定义 dp[i][0] 表示考虑前 i 个预约,第 i 个预约不接的最长预约时间,dp[i][1] 表示考虑前 i 个预约,第
i 个预约接的最长预约时间。

从前往后计算 dp 值,假设我们已经计算出前 i−1 个 dp 值,考虑计算 dp[i][0/1] 的答案。

首先考虑 dp[i][0] 的转移方程,由于这个状态下第 i 个预约是不接的,所以第 i−1 个预约接或不接都可以,故可以从 dp[i−1][0] 和 dp[i−1][1] 两个状态转移过来,转移方程即为:
dp[i][0]=max(dp[i−1][0],dp[i−1][1])

对于 dp[i][1] ,由于这个状态下第 i 个预约要接,根据题目要求按摩师不能接受相邻的预约,所以第
i−1 个预约不能接受,故我们只能从 dp[i−1][0] 这个状态转移过来,转移方程即为:

dp[i][1]=dp[i−1][0]+nums。 其中 nums 表示第 i 个预约的时长。

最后答案即为 :
max(dp[n][0],dp[n][1]) ,其中 n 表示预约的个数。

再回来看转移方程,我们发现计算 dp[i][0/1] 时,只与前一个状态 dp[i−1][0/1] 有关,所以我们可以不用开数组,只用两个变量 分别存储 dp[i−1][0] 和 dp[i−1][1] 的答案,然后去转移更新答案即可。

3.2、代码实现

class Solution {
public:
    int massage(vector<int>& nums) {
        int n = (int)nums.size();
        if (!n) {
            return 0;
        }
        int dp0 = 0, dp1 = nums[0];

        for (int i = 1; i < n; ++i){
            int tdp0 = max(dp0, dp1); // 计算 dp[i][0]
            int tdp1 = dp0 + nums[i]; // 计算 dp[i][1]

            dp0 = tdp0; // 用 dp[i][0] 更新 dp_0
            dp1 = tdp1; // 用 dp[i][1] 更新 dp_1
        }
        return max(dp0, dp1);
    }
};

时间复杂度:O(n),其中 n 为预约的个数。有 2n 个状态需要计算,每次状态转移需要 O(1) 的时间,所以一共需要 O(2n)=O(n) 的时间复杂度。

空间复杂度:O(1),只需要常数的空间存放若干变量。

总结

动态规划(Dynamic Programming)是一种解决多阶段决策最优化问题的方法,它将复杂问题分解成重叠子问题并通过维护每个子问题的最优解来推导出问题的最优解。动态规划可以解决许多实际问题,例如最短路径问题、背包问题、最长公共子序列问题、编辑距离问题等。

动态规划的基本思想是利用已求解的子问题的最优解来推导出更大问题的最优解,从而避免了重复计算。它通常采用自底向上的方式进行求解,先求解出小规模的问题,然后逐步推导出更大规模的问题,直到求解出整个问题的最优解。

动态规划通常包括以下几个基本步骤:

  1. 定义状态:将问题划分为若干个子问题,并定义状态表示子问题的解;
  2. 定义状态转移方程:根据子问题之间的关系,设计状态转移方程,即如何从已知状态推导出未知状态的计算过程;
  3. 确定初始状态:定义最小的子问题的解;
  4. 自底向上求解:按照状态转移方程,计算出所有状态的最优解;
  5. 根据最优解构造问题的解。

动态规划的时间复杂度通常为 O ( n 2 ) O(n^2) O(n2) O ( n 3 ) O(n^3) O(n3),空间复杂度为O(n),其中n表示问题规模。在实际应用中,为了减少空间复杂度,通常可以使用滚动数组等技巧来优化动态规划算法。

在这里插入图片描述

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

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

相关文章

python spider 爬虫 之 scrapy框架 企业级

Scrapy定义 它是一个为了爬取网站的数据&#xff0c;提取结构性数据而编写的应用框架。可以应用在包括数据挖掘信息处理或存储历史数据等一系列的程序中 Scrapy 安装 pip install scrapy 安装过程中可能出现的错误&#xff1a; 报错1&#xff1a;building ‘twisted.test.r…

如何将银行卡拍照转为excel?

如果您手头上有很多的银行卡&#xff0c;并且需要录入到电脑&#xff0c;怎么办&#xff1f;手工一张一张、一个数字一个数字地敲键盘打字&#xff1f;太麻烦了&#xff0c;效率低&#xff0c;而且银行卡上的卡号数字可不短&#xff0c;传统的人工打字录入很容易出错&#xff0…

基于模糊控制算法的水位控制研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

Qt 动态手势识别“手掌随动”+“握拳选择”

系列文章目录 通过Qt实现手势识别控制软件操作相关系列技术方案 &#xff08;一&#xff09;Qt 将某控件、图案绘制在最前面的方法&#xff0c;通过QGraphicsScene模块实现 &#xff08;二&#xff09;Qt QGraphicsScene模块实现圆点绘制在所有窗体的最前方&#xff0c;实现圆…

leetcode583. 两个字符串的删除操作(java-动态规划)

两个字符串的删除操作 leetcode583. 两个字符串的删除操作题目描述解题思路解法一 递归加缓存动态规划代码演示 动态规划专题 leetcode583. 两个字符串的删除操作 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/delete-…

算法基础修炼

算法基础 数据结构与算法 字符串匹配 KMP算法&#xff1a; 字符串算法之KMP&#xff08;字符串匹配&#xff09;kmp字符串匹配算法青萍之末的博客-CSDN博客 各大排序算法&#xff1a; 冒泡排序&#xff1a; 选择排序&#xff1a; 类似于冒泡算法&#xff0c;不断找到乱…

Android 编译Android7.0版本源码

编译Android7.0版本源码 前言正文一、前置条件二、编译准备三、下载编译源码1. 下载Repo2. 初始化仓库3. 同步远程代码4. 编译源码5. 启动模拟器 四、编译中的问题① Jack-Server② 本地化设置③ Communication error with Jack server (35), try jack-diagnose or see Jack se…

Pycharm中运行Allure报错不是内部或外部命令的解决方案

问题现象&#xff1a; Allure已安装并配置好系统环境变量&#xff1a; 1、Allure的下载地址&#xff1a;https://github.com/allure-framework/allure2/releases 2、下载后解压&#xff0c;将解压后的bin路径配置到环境变量中&#xff1a; allure-pytest插件也已安装好&#x…

Thinkphp5分页后携带参数进行跳转传递

问题&#xff1a; 我在tp框架中写了一个图书详情分页的&#xff0c;代码如下&#xff1a; public function verify_details(){$sell_order_numinput(sell_order_num);$resDB::table(verif)->where(["sell_order_num">$sell_order_num])->paginate(10);// 模…

Linux上安装matlab

首先需要下载文件&#xff0c;微人大正版软件下载里有 然后直接点击&#xff0c;就可以就可以安装&#xff0c;不需要使用挂载命令&#xff0c;然后使用 ./install就可以进行安装了&#xff0c;这里记住是得登录自己的人大邮箱&#xff0c;否则无法激活&#xff0c;然后修改安…

LINUX7下安装kaldi实战

LINUX7下安装kaldi实战&#xff0c;需要升级gcc版本。还需要将kaldi相关的github.com替换为kgithub.com。 1 升级安装gcc过程 我是在LINUX7.5下安装部署得kaldi。自带的gcc版本为4.8.5&#xff0c;所以需要安装升级gcc. 1.1 安装说明 gcc库包含3个依赖库&#xff1a;gmp、m…

【各种乐器波形图】笛子、二胡、钢琴、号角等乐器波形图研究

标题&#xff1a;不同乐器波形图 笛子的频率取决于其音高&#xff0c;不同音高的笛子频率也不同。以C调笛子为例&#xff0c;其最基本的频率为261.63 Hz&#xff08;即中央C的频率&#xff09;。而其他调号的笛子的基本频率则会有所不同。 笛子的波形图&#xff1a; import n…

有奖问卷 | 2023 中国软件研发效能调查问卷即将截止

中国信通院将根据问卷征集和企业调研结果&#xff0c;与业内专家共同撰写**《2023 中国软件研发效能调查报告》**&#xff0c;研判发展趋势&#xff0c;提供研发效能体系建设建议&#xff0c;并于 2023 年 7 月 7 日正式发布调查报告解读。 随着云计算应用的不断深入&#xff0…

微信小程序中使用echart、动态加载几条折线

一、示例 echart小程序示例 gitub地址&#xff1a;GitHub - ecomfe/echarts-for-weixin: Apache ECharts 的微信小程序版本 在小程序中放入 效果 二、 小程序代码 json 组件的位置取决于一示例中的的echart的位置 { "navigationStyle":"custom","…

STM32速成笔记—EEPROM(AT24C02)

文章目录 一、AT24C02简介二、AT24C02引脚三、AT24C02寻址四、AT24C02读/写操作4.1 AT24C02写操作4.2 AT24C02读操作 五、AT24C02程序六、应用实例七、拓展应用 一、AT24C02简介 AT24C01/02/04/08/16…是一个1K/2K/4K/8K/16K位电可擦除PROM&#xff0c;内部含有128/256/512/10…

数据中心供配电系统负荷的计算方法(三)

数据中心供配电系统是为机房内所有需要动力电源的设备提供稳定、可靠的动力电源支持的系统&#xff1b;是数据中心日常运维的重大支出之一&#xff0c;在数据中心&#xff0c;供配电系统相当于一个人的“心脏和血管”&#xff0c;负责把能量输送到系统的每一台设备。一旦供配电…

伦敦金价格实时查询

伦敦金是具有显著杠杆效应的投资品种&#xff0c;参与其中的投资者&#xff0c;往往需要时刻关注它的实时行情走势&#xff0c;以及自己交易账户内的情况&#xff0c;才能及时地兑现利润和控制交易的风险。所以对于每一位伦敦金投资者来说&#xff0c;实时的行情报价都是十分重…

stable-diffusion 预训练模型汇总

目前各个github上各个库比较杂乱&#xff0c;故此做些整理方便查询 Stable UnCLIP 2.1 New stable diffusion finetune (Stable unCLIP 2.1, Hugging Face) at 768x768 resolution, based on SD2.1-768. This model allows for image variations and mixing operations as d…

OA办公系统如何通过审批流程提高效率

企业的发展与管理离不开信息化&#xff0c;很多企业的信息化都会选择从OA信息化开始。一个成熟先进的OA办公系统流程审批也是核心功能关注的功能之一&#xff0c;今天小编举例有18年平台经验的天翎低代码平台OA系统&#xff0c;给大家分享一下如果提升流程审批效率&#xff1a;…

展会回顾|万应低代码重磅亮相2023全球人工智能产品应用博览会

6月25-27日&#xff0c;人工智能领域的行业盛会——第五届全球人工智能产品应用博览会&#xff08;简称“全球智博会”&#xff09;在苏州国际博览中心成功举行。大会由苏州市人民政府指导、苏州工业园区管理委员会支持、新一代人工智能产业技术创新战略联盟、苏州市人工智能协…