代码随想录算法训练营 | 动态规划 part08

news2024/9/22 11:37:06

121. 买卖股票的最佳时机

121. 买卖股票的最佳时机

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。
你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。
返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

在这里插入图片描述
贪心
只能买卖一次
在某一天买入:希望在股票价格最低的一天买入;
未来的某一个不同的日子 卖出:在未来的价格最高的一天卖出;
如此,获得的利润最大;

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int res = 0;
        int minPirce = prices[0];
        for (int i = 1; i < prices.size(); i++) {
            res = max(res, prices[i] - minPirce);
            minPirce = min(minPirce, prices[i]);
        }
        return res;
    }
};

动态规划
n 为表示股票价格数组的长度;
i 表示第 i 天(i0 开始到 n - 1);
k 表示允许(交易)的 最多 次数;
dp[i][k] 表示在第 i 天 最多 进行 k 笔交易获得的最大利润。
初始条件:dp[-1][k] = dp[i][0] = 0dp[-1][k]这里第一天对应 i = 0,所以第 -1 天没有股票交易;dp[i][0]即如果没有交易,就不产生任何利润;
i 天可以:买入、卖出、不进行任何操作;目的是使最终利润最大;
本题只能交易一次;意味着全程最多持有一支股票;假设在第 i 天买入股票,则买入之前持有 0 支股票;假设在第 i 天卖出股票,则卖出之前正好持有 1 支股票;第 i 天持有几只股票会影响我们在第 i 天的操作,继而影响最大利润;
综上所述,对 dp[i][k] 的应该分为两个部分:dp[i][k][0]dp[i][k][1]
dp[i][k][0] 表示第 i 天进行最多进行 k 笔交易并且完成以后,我们当前不持股而获得的利润;
dp[i][k][1] 表示第 i 天进行最多进行 k 笔交易并且完成以后,我们当前持股而获得的利润;
base cases:

dp[-1][k][0] = 0; // -1天
dp[-1][k][1] = -Infinity; // 没有进行股票交易时不允许持有股票

dp[i][0][0] = 0; // 没有交易,没有利润
dp[i][0][1] = -Infinity; // 没有进行股票交易时不允许持有股票

状态转移方程:

dp[i][k][0] = max(dp[i - 1][k][0], dp[i - 1][k][1] + prices[i]);
dp[i][k][1] = max(dp[i - 1][k][1], dp[i - 1][k - 1][0] - prices[i]);

dp[i][k][0]i 天只能是无任何操作或卖出;当第 i 天无任何操作时,当天持股为0,则第 i - 1 天所有交易完成后,为不持股状态dp[i - 1][k][0],即为无操作的最大利润;当第 i 天卖出时,卖出之前持股为1,则第 i - 1 天所有交易完成后,为持股状态dp[i - 1][k][1],卖出的最大利润为第 i - 1 天持股的最大利润加上第 i 天卖出股票的金额;
dp[i][k][1]i 天只能是无任何操作或买入;当第 i 天无任何操作时,当天持股为1,则第 i - 1 天所有交易完成后,为持股状态dp[i - 1][k][1],即为无操作的最大利润;当第 i 天买入时,买入之前持股为0,则第 i - 1 天所有交易完成后,为持股状态dp[i - 1][k - 1][0](这里最大交易次数减少一次,是因为买入操作会使用一次交易(买入-卖出为一次交易)),买入的最大利润为第 i - 1 天持股的最大利润减去第 i 天买入股票的金额;
最终的最大利润是 dp[n - 1][k][0],因为结束时持有 0 份股票的收益一定大于持有 1 份股票的收益。

回到本题:k = 1
状态转移方程:

dp[i][1][0] = max(dp[i - 1][1][0], dp[i - 1][1][1] + prices[i]);
dp[i][1][1] = max(dp[i - 1][1][1], dp[i - 1][0][0] - prices[i]) = max(dp[i - 1][1][1], - prices[i]);

因为dp[i][0][0] = 0;
优化为二维数组:

dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
dp[i][1] = max(dp[i - 1][1], - prices[i]);
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        vector<vector<int>> dp(prices.size(), vector<int>(2));
        dp[0][0] = 0;
        dp[0][1] = -prices[0];
        for (int i = 1; i < prices.size(); i++) {
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
            dp[i][1] = max(dp[i - 1][1], -prices[i]);
        }
        return dp[prices.size() - 1][0];
    }
};

i 天的最大利润只和第 i - 1 天的最大利润相关,也可以继续优化为常数级

122.买卖股票的最佳时机II

122.买卖股票的最佳时机II

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。
在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。
返回 你能获得的 最大 利润 。

可以买卖多次
贪心

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int res = 0;
        for (int i = 0; i < prices.size() - 1; i++) {
            int diff = prices[i + 1] - prices[i];
            if (diff > 0) {
                res += diff;
            }
        }
        return res;
    }
};

动态规划
本题:k = +Infinity,同时最多可以持有一支股票;

dp[i][k][0] = max(dp[i - 1][k][0], dp[i - 1][k][1] + prices[i]);
dp[i][k][1] = max(dp[i - 1][k][1], dp[i - 1][k - 1][0] - prices[i]);

因为k = +Infinity,所以 k 和 k - 1 可以看成相同的;

dp[i][k][0] = max(dp[i - 1][k][0], dp[i - 1][k][1] + prices[i]);
dp[i][k][1] = max(dp[i - 1][k][1], dp[i - 1][k][0] - prices[i]);

优化成二维数组

dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        vector<vector<int>> dp(prices.size(), vector<int>(2));
        dp[0][0] = 0;
        dp[0][1] = -prices[0];
        for (int i = 1; i < prices.size(); i++) {
            dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
            dp[i][1] = max(dp[i - 1][1], dp[i - 1][0]-prices[i]);
        }
        return dp[prices.size() - 1][0];
    }
};

i 天的最大利润只和第 i - 1 天的最大利润相关,也可以继续优化为常数级

123.买卖股票的最佳时机III

123.买卖股票的最佳时机III

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

本题:最多买卖两次,k = 2

dp[i][k][0] = max(dp[i - 1][k][0], dp[i - 1][k][1] + prices[i]);
dp[i][k][1] = max(dp[i - 1][k][1], dp[i - 1][k - 1][0] - prices[i]);

因为k = 2,所以有:

dp[i][1][0] = max(dp[i - 1][1][0], dp[i - 1][1][1] + prices[i]);
dp[i][1][1] = max(dp[i - 1][1][1], dp[i - 1][0][0] - prices[i]) = max(dp[i - 1][1][1], - prices[i]);
dp[i][2][0] = max(dp[i - 1][2][0], dp[i - 1][2][1] + prices[i]);
dp[i][2][1] = max(dp[i - 1][2][1], dp[i - 1][1][0] - prices[i]);
class Solution {
public:
    int maxProfit(vector<int>& prices) {
        vector<vector<vector<int>>> dp(prices.size(), vector<vector<int>>(3, vector<int>(2)));
        dp[0][1][0] = 0;
        dp[0][1][1] = -prices[0];
        dp[0][2][0] = 0;
        dp[0][2][1] = -prices[0];
        for (int i = 1; i < prices.size(); i++) {
            dp[i][1][0] = max(dp[i - 1][1][0], dp[i - 1][1][1] + prices[i]);
            dp[i][1][1] = max(dp[i - 1][1][1], - prices[i]);
            dp[i][2][0] = max(dp[i - 1][2][0], dp[i - 1][2][1] + prices[i]);
            dp[i][2][1] = max(dp[i - 1][2][1], dp[i - 1][1][0] - prices[i]);
        }
        return dp[prices.size() - 1][2][0];
    }
};

i 天的最大利润只和第 i - 1 天的最大利润相关,也可以继续优化为常数级

class Solution {
public:
    int maxProfit(vector<int>& prices) {
        int profitOne0 = 0;
        int profitOne1 = -prices[0];
        int profitTwo0 = 0;
        int profitTwo1 = -prices[0];
        for (int i = 1; i < prices.size(); i++) {
            profitOne0 = max(profitOne0, profitOne1 + prices[i]);
            profitOne1 = max(profitOne1, - prices[i]);
            profitTwo0 = max(profitTwo0, profitTwo1 + prices[i]);
            profitTwo1 = max(profitTwo1, profitOne0 - prices[i]);
        }
        return profitTwo0;
    }
};

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

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

相关文章

轻松入门大模型:150页精炼指南,简化你的学习之路

如果问个问题&#xff1a;有哪些产品曾经创造了伟大的奇迹&#xff1f;ChatGPT 应该会当之无愧入选。仅仅发布 5 天&#xff0c;ChatGPT 就吸引了 100 万用户——当然&#xff0c;数据不是关键&#xff0c;关键是其背后的技术开启了新的 AI 狂潮&#xff0c;成为技术变革的点火…

ctfshow-web入门-sql注入(web231-web236)update 注入

目录 1、web231 2、web232 3、web233 4、web234 5、web235 6、web236 1、web231 拼接的是 update 语句 //分页查询$sql "update ctfshow_user set pass {$password} where username {$username};"; password 和 username 可控&#xff0c;注入地方还是在 …

laravel发送邮件的使用方法?有哪些技巧?

laravel发送邮件怎么实现&#xff1f;如何使用Laravel发送邮件&#xff1f; Laravel&#xff0c;作为一个流行的PHP框架&#xff0c;提供了强大且灵活的邮件发送功能&#xff0c;使得开发者可以轻松地集成邮件服务到他们的应用中。AokSend将详细介绍如何在Laravel中使用larave…

conda虚拟环境中安装cuda和cudnn

目录 一、cuda安装步骤 1&#xff09;cuda的安装 1、查看conda支持的cuda版本 2、下载cuda并安装cuda 2&#xff09;cudnn的安装 1、查看cuda对应的cudnn版本 2、下载cudnn并安装 二、torch的安装和tensorflow的安装 1&#xff09;安装tensorflow 1、确定安装版本并安…

Java入门:06.Java中的方法--进阶02.03

2 可变参数 方法调用时&#xff0c; 传递的实参数量&#xff0c;是由被调用方法的参数列表数列决定的。 一般来讲&#xff0c;传递的实参数量必须与形参变量数量相同&#xff0c;但是也有一种特殊的参数&#xff0c;允许调用时传递的实参数量是可变&#xff0c;这种参数就称为…

《黑神话·悟空》游戏开发教程来了,全部开源。。。

黑神话悟空游戏&#xff0c;官网说明使用UE5引擎开发. 这篇文章发一个UE5游戏开发的系统教程。 1 开发悟空游戏的UE5 UE5&#xff0c;即 Unreal Engine 5&#xff0c;是由 Epic Games 开发的一款高度先进的游戏引擎。 UE5 是 Unreal Engine 系列的最新版本&#xff0c;它提供…

Qt第十八章 XML和Json格式解析

文章目录 JSON格式解析Json生成案例 XML简介与HTML的区别格式XML解析流的方式DOM XML生成 JSON与XML的区别比较 JSON 格式 JSON是一个标记符的序列。这套标记符包含六个构造字符、字符串、数字和三个字面名 六个构造字符 开始和结束数组&#xff1a;[ ]开始和结束对象&#x…

应用商场的搭建

前言&#xff1a; 使用mysql做主从设置&#xff0c;redis数据库做热门访问数据库。mycat读写分离&#xff0c;zookeeperkafka做数据收集&#xff0c;使用三台虚拟机 关掉防火墙和selinux,做时间同步 192.168.121.11 node1 mycat.example.com 192.168.121.21 node2 …

提高LabVIEW电机控制速度

在LabVIEW中执行绝对位移命令时&#xff0c;其运行时间主要与以下电机参数有关&#xff1a; 电机加速度和减速度&#xff1a; 加速度和减速度参数决定了电机从静止到达到目标速度&#xff0c;以及从高速到停止的时间。这些参数直接影响电机响应的迅速程度。如果加速度和减速度设…

如何使用ssm实现基于bs模式的医院在线挂号预约系统的设计与实现

TOC ssm072基于bs模式的医院在线挂号预约系统的设计与实现jsp 第1章 绪论 1.1 课题背景 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人…

B/S架构和C/S架构的区别

B/S架构、C/S架构区别 1. B/S架构 1.1 什么是B/S架构 B/S架构的全称为Browser/Server&#xff0c;即浏览器/服务器结构。Browser指的是Web浏览器&#xff0c;极少数事务逻辑在前端实现&#xff0c;但主要事务逻辑在服务器端实现。B/S架构的系统无须特别安装&#xff0c;只需要…

实战OpenCV之绘制图形

基础入门 OpenCV除了用于图像显示之外&#xff0c;还提供了一系列接口和工具&#xff0c;以帮助开发者在图像上绘制各种图形。这里的图形包括&#xff1a;直线、矩形、圆形、椭圆、多边形等。另外&#xff0c;OpenCV还支持在图像上添加文字&#xff0c;对多张图像进行叠加操作。…

NACOS 2.4.1如何开启账号密码登录功能

Nacos Server 2.4.0+已正式发布取消管理员用户 nacos 的默认密码支持初始化指定密码。 本章教程,主要介绍如何给nacos加上鉴权,支持通过用户名和密码的方式进行访问nacos页面。 NACOS 2.4.1版本下载地址:https://github.com/alibaba/nacos/releases/tag/2.4.1 1、开启认证功…

驱动:insmod

一、驱动模块的加载 1. 静态 编译进内核2. 动态 编译成模块 如下&#xff1a; 解决方法 结果 led电灯例子 创建一个led.c 修改Makefile、Kconfigmake modulescp drivers/char/led.ko /home/linux/nfs/rootfs开发板 insmod led.ko去 /home/linux/nfs/rootfs 上 写程序.carm-l…

每日掌握一个科研绘图|区域图·24-08-23

小罗碎碎念 为了方便大家获取对应的代码和源数据&#xff0c;从本期推文开始&#xff0c;我将把对应的文件上传至Github仓库&#xff0c;感兴趣的同学自行获取。 仓库地址 https://github.com/Lxltxpku/Share 一、区域图 区域图是一种数据可视化工具&#xff0c;它通过在坐标…

嵌入式人工智能ESP32(7-OLED显示中英文)

1、OLED显示英文 我们之前通过树莓派开发板做过OLED显示&#xff0c;这里就不再赘述OLED显示屏了。直接上接线图与代码。 &#xff08;1&#xff09;Adafruit Adafruit是一家成立于2005年的私营企业&#xff0c;主要业务是设计和制造开源电子硬件。Adafruit在美国设计和制造其…

全栈杂谈第一期:什么是计算机中的并发

什么是计算机中的并发 计算机中的“并发”是一个听起来很复杂的词汇&#xff0c;但我们可以把它简单理解为“同时做很多事情”。想象一下你正在做晚饭&#xff1a;你可以在等水烧开的时候切菜&#xff0c;还可以在等待炖汤时洗碗。尽管你只有一双手&#xff0c;但通过合理安排…

芋道cloud v2.2.0发布,支持模块选配,丢弃简易版

大家知道&#xff0c;芋道cloud拥有商城、CRM、ERP、微信相关等模块&#xff0c;很显然我们在日常开发中不可能一个项目同时拥有这么多模块。但是从gitee上获取代码的时候&#xff0c;只提供了简易版和完整版。简易版本只有最基础的功能&#xff0c;如果想要微信相关的模块&…

浅谈Llama3.1,从结构、训练过程、影响到数据合成

Llama3.1系列模型的开源&#xff0c;真让大模型格局大震&#xff0c;指标上堪比最好的闭源模型比如GPT 4o和Claude3.5&#xff0c;让开源追赶闭源成为现实。 这里给大家分享一篇俊林兄&#xff08;知乎张俊林&#xff09;的一篇解读&#xff0c;主要对LLaMA3.1的模型结构、训练…

RM双轴云台控制

RM机器人上最复杂的控制计构就是双轴云台了&#xff0c;赛场上的情况对双轴云台的控制稳定度与响应灵敏度双方面都提出了很高的要求&#xff0c;云台控制的好坏在一定程度上就能够代表一支队伍的实力。 双轴云台采用的控制算法依然是PID控制算法&#xff0c;关于PID控制算法的…