代码随想录算法训练营第41天|LeetCode 121. 买卖股票的最佳时机、122.买卖股票的最佳时机II、123.买卖股票的最佳时机III

news2024/9/21 20:24:12

1. LeetCode 121. 买卖股票的最佳时机

题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock/description/
文章链接:https://programmercarl.com/0121.买卖股票的最佳时机.html#思路
视频链接:https://www.bilibili.com/video/BV1Xe4y1u77q

在这里插入图片描述

思路:
1.确定dp数组(dp table)以及下标的含义。
dp[i][0] 表示第i天持有股票所得最多现金;
dp[i][1] 表示第i天不持有股票所得最多现金。
2.确定递推公式
1️⃣如果第i天持有股票即dp[i][0], 那么可以由两个状态推出来
第i-1天就持有股票,那么就保持现状,所得现金就是昨天持有股票的所得现金 即:dp[i - 1][0];
第i天买入股票,所得现金就是买入今天的股票后所得现金即:-prices[i]
那么dp[i][0]应该选所得现金最大的,所以dp[i][0] = max(dp[i - 1][0], -prices[i]);
2️⃣如果第i天不持有股票即dp[i][1], 也可以由两个状态推出来
第i-1天就不持有股票,那么就保持现状,所得现金就是昨天不持有股票的所得现金 即:dp[i - 1][1]
第i天卖出股票,所得现金就是按照今天股票价格卖出后所得现金即:prices[i] + dp[i - 1][0]
那么dp[i][1]取最大的,dp[i][1] = max(dp[i - 1][1], prices[i] + dp[i - 1][0]);
3.初始化
dp[0][0] -= prices[0];
dp[0][1] = 0;
4.遍历顺序
从前向后遍历。

解法:
class Solution {
    public int maxProfit(int[] prices) {
        if (prices.length==0 || prices.length==1) return 0;
        //1.定义dp数组 
        //dp[i][0]表示第i天持有股票金额
        //dp[i][1]表示第i天不持有股票金额
        int[][] dp = new int[prices.length][2];
        //2.递推公式
        //dp[i][0] = Math.max(dp[i-1][0],-prices[i]);
        //dp[i][1] = Math.max(dp[i-1][1],prices[i]+dp[i-1][0]);
        //3.初始化
        dp[0][0]=-prices[0];
        dp[0][1]=0;
        //4.遍历顺序
        for (int i=1;i<prices.length;i++) {
            dp[i][0] = Math.max(dp[i-1][0],-prices[i]);
            dp[i][1] = Math.max(dp[i-1][1],prices[i]+dp[i-1][0]);
        }

        return dp[prices.length-1][1];
    }
}

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

题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/description/
文章链接:https://programmercarl.com/0122.买卖股票的最佳时机II(动态规划).html
视频链接:https://www.bilibili.com/video/BV1D24y1Q7Ls

在这里插入图片描述

思路:
本题和121. 买卖股票的最佳时机 (opens new window)的唯一区别是本题股票可以买卖多次了(注意只有一只股票,所以再次购买前要出售掉之前的股票)
递推公式:
1️⃣如果第i天持有股票即dp[i][0], 那么可以由两个状态推出来:
第i-1天就持有股票,那么就保持现状,所得现金就是昨天持有股票的所得现金 即:dp[i - 1][0]
第i天买入股票,所得现金就是昨天不持有股票的所得现金减去 今天的股票价格 即:dp[i - 1][1] - prices[i]
2️⃣如果第i天不持有股票即dp[i][1]的情况, 依然可以由两个状态推出来:
第i-1天就不持有股票,那么就保持现状,所得现金就是昨天不持有股票的所得现金 即:dp[i - 1][1]
第i天卖出股票,所得现金就是按照今天股票价格卖出后所得现金即:prices[i] + dp[i - 1][0]

class Solution {
    // // 贪心
    // public int maxProfit(int[] prices) {
    //     int res = 0;
    //     for (int i=1;i<prices.length;i++) {
    //         if (prices[i]-prices[i-1] > 0) {
    //             res += (prices[i]-prices[i-1]);
    //         }
    //     }
    //     return res;
    // }

    // //动态规划 1
    // public int maxProfit(int[] prices) {
    //     //1.定义dp数组
    //     //dp[i]表示第i天的最大利润
    //     int[] dp = new int[prices.length];
    //     //2.递推公式
    //     //dp[i]=Math.max(dp[i-1],dp[i-1]+(prices[i]-prices[i-1]));
    //     //3.初始化
    //     dp[0]=0;
    //     //4.遍历顺序
    //     for (int i=1;i<prices.length;i++) {
    //         dp[i]=Math.max(dp[i-1],dp[i-1]+(prices[i]-prices[i-1]));
    //     }
    //     return dp[prices.length-1];
    // }
    //动态规划 2
    public int maxProfit(int[] prices) {
        //1.定义dp数组
        //dp[i][0]表示第i天持有股票的金额
        //dp[i][1]表示第i天不持有股票的金额
        int[][] dp = new int[prices.length][2];
        //2.递推公式
        //dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]-prices[i]);
        //dp[i][1]=Math.max(dp[i-1][1],dp[i-1][0]+prices[i]);
        //3.初始化
        dp[0][0]=-prices[0];
        dp[0][1]=0;
        //4.遍历顺序
        for (int i=1;i<prices.length;i++) {
            dp[i][0]=Math.max(dp[i-1][0],dp[i-1][1]-prices[i]);
            dp[i][1]=Math.max(dp[i-1][1],dp[i-1][0]+prices[i]);
        }

        return dp[prices.length-1][1];
    }
}

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

题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iii/description/
文章链接:https://programmercarl.com/0123.买卖股票的最佳时机III.html
视频链接:https://www.bilibili.com/video/BV1WG411K7AR

在这里插入图片描述

思路:
关键在于至多买卖两次,这意味着可以买卖一次,可以买卖两次,也可以不买卖。

1.确定dp数组以及下标的含义
一天一共就有五个状态:
0 没有操作 (其实我们也可以不设置这个状态)
1 第一次持有股票时的金额
2 第一次不持有股票时的金额
3 第二次持有股票时的金额
4 第二次不持有股票时的金额
dp[i][j]中 i表示第i天,j为 [0 - 4] 五个状态,dp[i][j]表示第i天状态j所剩最大现金。
2.确定递推公式
1️⃣dp[i][1]状态表示第i天第一次持有股票时的金额,有两个具体操作:
操作一:第i天买入股票了,那么dp[i][1] = - prices[i]
操作二:第i天没有操作,而是沿用前一天买入的状态,即:dp[i][1] = dp[i - 1][1]
选最大的,则递推公式为:dp[i][1] = max(-prices[i], dp[i - 1][1]);
2️⃣dp[i][2]状态表示第i天第一次不持有股票时的金额,有两个操作:
操作一:第i天卖出股票了,那么dp[i][2] = dp[i - 1][1] + prices[i]
操作二:第i天没有操作,沿用前一天卖出股票的状态,即:dp[i][2] = dp[i - 1][2]
选最大的,则递推公式为:p[i][2] = max(dp[i - 1][1] + prices[i], dp[i - 1][2]);
3️⃣dp[i][3]状态表示第i天第二次持有股票时的金额,有两个具体操作:
操作一:第i天买入股票了,那么dp[i][3] = dp[i-1][2] - prices[i]
操作二:第i天没有操作,而是沿用前一天买入的状态,即:dp[i][3] = dp[i - 1][3]
选最大的,则递推公式为:dp[i][3] = max(dp[i-1][2] - prices[i], dp[i - 1][3]);
4️⃣dp[i][4]状态表示第i天第二次不持有股票时的金额,有两个操作:
操作一:第i天卖出股票了,那么dp[i][4] = dp[i - 1][3] + prices[i]
操作二:第i天没有操作,沿用前一天卖出股票的状态,即:dp[i][4] = dp[i - 1][4]
选最大的,则递推公式为:p[i][4] = max(dp[i - 1][3] + prices[i], dp[i - 1][4]);
3.dp数组如何初始化
dp[0][0]=0;
dp[0][1]=-prices[0];
dp[0][2]=0;
dp[0][3]=-prices[0];
dp[0][4]=0;
4.确定遍历顺序
从递归公式其实已经可以看出,一定是从前向后遍历,因为dp[i],依靠dp[i - 1]的数值。

class Solution {
    public int maxProfit(int[] prices) {
       //1.定义dp数组
       //dp[i][0] 第i天没有操作
       //dp[i][1] 第i天第一次持有股票时的金额
       //dp[i][2] 第i天第一次不持有股票时的金额
       //dp[i][3] 第i天第二次持有股票时的金额
       //dp[i][4] 第i天第二次不持有股票时的金额
       int[][] dp = new int[prices.length][5];
       //2.递推公式
       //dp[i][1]=Math.max(dp[i-1][1],-prices[i]);
       //dp[i][2]=Math.max(dp[i-1][2],dp[i-1][1]+prices[i]);
       //dp[i][3]=Math.max(dp[i-1][3],dp[i-1][2]-prices[i]);
       //dp[i][4]=Math.max(dp[i-1][4],dp[i-1][3]+prices[i]);
       //3.初始化
       dp[0][0]=0;
       dp[0][1]=-prices[0];
       dp[0][2]=0;
       dp[0][3]=-prices[0];
       dp[0][4]=0;
       //4.遍历顺序 从前往后
       for (int i=1;i<prices.length;i++) {
            dp[i][1]=Math.max(dp[i-1][1],-prices[i]);
            dp[i][2]=Math.max(dp[i-1][2],dp[i-1][1]+prices[i]);
            dp[i][3]=Math.max(dp[i-1][3],dp[i-1][2]-prices[i]);
            dp[i][4]=Math.max(dp[i-1][4],dp[i-1][3]+prices[i]);
       }

       return dp[prices.length-1][4];
    }
}

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

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

相关文章

微调基模型

该示例用的谷歌的gemma-2b-it模型 Gemma是Google的一系列轻量级、最先进的开源模型&#xff0c;基于用于创建Gemini模型的相同研究和技术构建。它们是文本到文本、仅解码的大型语言模型&#xff0c;提供英文、开源权重、预训练变体和指令调优变体。Gemma模型非常适合各种文本生…

微软蓝屏事件:网络安全与系统稳定性的深刻反思

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 公众号&#xff1a;网络豆云计算学堂 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a; 网络豆的主页​​​​​ 写在前面 在数字化时代&#xff0c;软件更新已成为…

电测量数据交换DLMS∕COSEM组件第61部分:对象标识系统(OBIS)(下)

GB/T 17215.6的本部分规定了对象标识系统(OBIS)的总体结构并将测量设备中的所有常用数据项映射到其标识代码。OBIS为测量设备中的所有数据都提供唯一的标识符,不仅包括测量值,而且还包括仪表设备的配置或获取测量设备运行状态的抽象数据。 5.抽象对象(A=0) 5.1通用和服…

yolov10来了!用yolov10训练自己的数据集(原理、训练、部署、应用)

一、引言 YOLOv9还没热乎呢&#xff0c;YOLOv10就出来了&#xff0c;太卷了&#xff01;太快了&#xff01; 自今年2月YOLOv9发布之后&#xff0c; YOLO&#xff08;You Only Look Once&#xff09; 系列的接力棒传到了清华大学研究人员的手上。YOLOv10推出的消息引发了AI界的…

【第七天】TCP三次握手四次挥手 HTTP的keep-Alive和TCP的keepalive

TCP三次握手四次挥手 既然要了解这些&#xff0c;首先我们要清楚一个概念&#xff0c;半连接队列和全连接队列&#xff1a; 在TCP三次握手中&#xff0c;Linux内核会维护两个队列来管理连接请求。 这两个队列的存在是为了处理并发连接请求&#xff0c;确保服务端能够有效管理新…

设计模式17-适配模式

设计模式17-适配模式 动机定义与结构C代码推导总结应用具体应用示例 动机 在软件系统中由于应用环境的变化常常需要将一些现存的对象。放到新的环境中去应用。但是新环境要求的接口是这些现存对象所不满足的。那么这种情况下如何应对这种迁移的变化&#xff1f;如何既能利用现…

《零散知识点 · SpringBoot 整合邮件功能》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

光伏气象仿真系统主要功能点

光伏电站的效能与经济效益受气象条件、地理位置、设计布局等多种因素影响显著。因此&#xff0c;光伏气象仿真系统应运而生&#xff0c;成为提升光伏项目规划、设计、运营管理水平的重要工具。该系统集成了气象数据分析、发电量分析、投融资分析、损耗估算分析及光伏设计等多项…

重磅惊喜!OpenAI突然上线GPT-4o超长输出模型!「Her」高级语音模式已开放测试

在最近的大模型战争中&#xff0c;OpenAI似乎很难维持霸主地位。虽然没有具体的数据统计&#xff0c;但Claude3.5出现后&#xff0c;只是看网友们的评论&#xff0c;就能感觉到OpenAI订阅用户的流失&#xff1a; Claude3.5比GPT-4o好用&#xff0c;为什么我们不去订阅Claude呢&…

【TS】基础(一)

TS基础学习 TS(TypeScript)TS的特性TS的优缺点优点缺点 TS和JS的区别TS常用类型原始类型数组类型别名 type联合类型 |函数对象接口 interface继承 extendsinterface和type的区别 类型断言枚举enum任意类型any TS(TypeScript) TS是JS类型的超集&#xff08;在JavaScript的基础上…

为什么说脱离决策的数据分析都是无用功

如果你问我数据分析师最重要的能力是什么&#xff0c;我的回答是数据驱动决策&#xff0c;这是数据分析师最值钱的能力&#xff0c;没有之一。 因为数据的价值在于挖掘&#xff0c;与业务和市场进行关联&#xff0c;找到机会点。抛开这个&#xff0c;数据本身一文不值&#xf…

C语言笔记(第n版):知识清单

注&#xff1a;本文参考自【C reference - cppreference.com】和【C 语言参考 | Microsoft Learn】&#xff0c;颇有点借花献佛的意味…… C 程序是一系列包含声明的文本文件&#xff08;通常为头文件和源文件&#xff09;的序列。它们经过转换成为可执行程序&#xff0c;当操作…

Bugku ---Web---全题目解析 超详细步骤 持续更新

目录 1.Simple_SSTI_1 2.Simple_SSTI_2 3.滑稽 4.计算器 5.矛盾 6.GET ————————————————————分割线———————————————————— 1.Simple_SSTI_1 SSTI是服务器端模板注入 F12查看下源码 在 Flask 中&#xff0c;双大括号 {{ }} 用…

ElasticSearch父子索引实战

关于父子索引 ES底层是Lucene,由于Lucene实际上是不支持嵌套类型的,所有文档都是以扁平的结构存储在Lucene中,ES对父子文档的支持,实际上也是采取了一种投机取巧的方式实现的. 父子文档均以独立的文档存入,然后添加关联关系,且父子文档必须在同一分片,由于父子类型文档并没有…

Oracle LiveLabs实验:Improve application performance with True Cache

此实验申请地址在这里&#xff0c;时间为120分钟。 帮助见这里。 简介 参加本次动手实践研讨会&#xff0c;了解如何使用 True Cache 通过卸载查询和减少对主数据库的请求和连接数量来提高可扩展性。本次研讨会基于连接到配置了 True Cache 的主数据库的计算实例&#xff08…

从零手写实现 mybatis 系列(零)mybatis 核心特性

拓展阅读 第一节 从零开始手写 mybatis&#xff08;一&#xff09;MVP 版本 中我们实现了一个最基本的可以运行的 mybatis。 第二节 从零开始手写 mybatis&#xff08;二&#xff09;mybatis interceptor 插件机制详解 第三节 从零开始手写 mybatis&#xff08;三&#xff0…

最低工资标准数据(2001-2023年不等)、省市县,整理好的面板数据(excel格式)

时间范围&#xff1a;2001-2022年 具体内容&#xff1a;一&#xff1a;最低工资数据标准时间&#xff1a;2012-2021包含指标&#xff1a; 省份城市/区县小时最低工资标准&#xff08;非全日制&#xff09;月最低工资标准实施日期 样例数据&#xff1a; 二&#xff1a;各省最低…

Spring Cloud Gateway网关的高级特性之GatewayFilter Factories(路由过滤器)

1、GatewayFilter Factories&#xff08;路由过滤器&#xff09; 官方访问地址&#xff1a;点击这里 来自官方的解释如下图所示&#xff1a; 简单来说就是&#xff1a; 客户端向 Spring Cloud Gateway 发送请求。如果请求与某个路由匹配&#xff0c;则该请求会被传递给 Ga…

OpenEuler安装部署教程

目录 OpenEuler安装部署教程 MobaXterm一款全能的远程工具 yum安装软件 vim编辑器&#xff08;了解&#xff09; 防火墙 常用命令 网络工具netstat & telnet 进程管理工具top ps 磁盘free、fdisk 用户、组&#xff08;了解&#xff09; 权限&#xff08;了解&am…