代码随想录算法训练营第五十天| 123.买卖股票的最佳时机III ,188.买卖股票的最佳时机IV

 题目与题解

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

题目链接:123.买卖股票的最佳时机III

代码随想录题解:​​​​​​​123.买卖股票的最佳时机III

视频讲解:动态规划,股票至多买卖两次,怎么求? | LeetCode:123.买卖股票最佳时机III_哔哩哔哩_bilibili

解题思路:

        其实就是沿用买卖股票II的思路,不同点在于有两次买卖,所以dp数组由n*2变为n*4。

        但是一开始没想通怎么写,直接看答案。

看完代码随想录之后的想法 

        关键在于明确dp的含义,和递推公式的概念。

一天一共就有五个状态,

  1. 没有操作 (其实我们也可以不设置这个状态)
  2. 第一次持有股票
  3. 第一次不持有股票
  4. 第二次持有股票
  5. 第二次不持有股票

dp[i][j]中 i表示第i天,j为 [0 - 4] 五个状态,dp[i][j]表示第i天状态j所剩最大现金。

达到dp[i][1]状态,有两个具体操作:

  • 操作一:第i天买入股票了,那么dp[i][1] = dp[i-1][0] - prices[i]
  • 操作二:第i天没有操作,而是沿用前一天买入的状态,即:dp[i][1] = dp[i - 1][1]

同理dp[i][2]也有两个操作:

  • 操作一:第i天卖出股票了,那么dp[i][2] = dp[i - 1][1] + prices[i]
  • 操作二:第i天没有操作,沿用前一天卖出股票的状态,即:dp[i][2] = dp[i - 1][2]

同理可推出剩下状态部分:

dp[i][3] = max(dp[i - 1][3], dp[i - 1][2] - prices[i]);

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

其实跟昨天的题是一样的,写的时候可以不用第0个状态,直接分4个状态。

class Solution {public int maxProfit(int[] prices) {if (prices.length <= 1) return 0;int[][] dp = new int[prices.length][4];dp[0][0] = -prices[0];dp[0][2] = -prices[0];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], dp[i-1][0] + 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]);}return dp[dp.length - 1][3];}
}

遇到的困难

        感觉dp的定义有点绕,但又很套路,复习的时候再仔细想想吧。

188.买卖股票的最佳时机IV

题目链接:188.买卖股票的最佳时机IV 

代码随想录题解:​​​​​​​188.买卖股票的最佳时机IV 

视频讲解:

动态规划来决定最佳时机,至多可以买卖K次!| LeetCode:188.买卖股票最佳时机4_哔哩哔哩_bilibili

解题思路:

        有前一题打底,其实很容易看出规律来,设置dp为n* 2*k的数组,2*k表示k次买入买出的状态,则递推公式中,dp[i][j]的j如果是偶数,表示持有股票状态,其值为

dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-1] - prices[i]);

dp[i][j]的j如果是奇数,表示持有股票状态,其值为

dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-1] + prices[i]);

初始化时,将j为奇数的dp[0][j]初始化为-prices[i]即可。

class Solution {public int maxProfit(int k, int[] prices) {if (prices.length <= 1) return 0;int[][] dp = new int[prices.length][k * 2];for (int i = 0; i < 2 * k; i = i+2) {dp[0][i] = -prices[0];}for (int i = 1; i < prices.length; i++) {dp[i][0] = Math.max(dp[i-1][0], -prices[i]);for (int j = 1; j < 2 * k; j += 2) {dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-1] + prices[i]);}for (int j = 2; j < 2 * k; j += 2) {dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-1] - prices[i]);}}return dp[dp.length - 1][2*k-1];}
}

看完代码随想录之后的想法 

        这个思路没啥好说的,写法可以优化一点,为了方便计算,可以设置一个第0天,初始化为0,就不用对第一天的数据做特殊处理了。另外,可以用一个循环同时更新奇偶数下标。

class Solution {public int maxProfit(int k, int[] prices) {if (prices.length == 0) return 0;// [天数][股票状态]// 股票状态: 奇数表示第 k 次交易持有/买入, 偶数表示第 k 次交易不持有/卖出, 0 表示没有操作int len = prices.length;int[][] dp = new int[len][k*2 + 1];// dp数组的初始化, 与版本一同理for (int i = 1; i < k*2; i += 2) {dp[0][i] = -prices[0];}for (int i = 1; i < len; i++) {for (int j = 0; j < k*2 - 1; j += 2) {dp[i][j + 1] = Math.max(dp[i - 1][j + 1], dp[i - 1][j] - prices[i]);dp[i][j + 2] = Math.max(dp[i - 1][j + 2], dp[i - 1][j + 1] + prices[i]);}}return dp[len - 1][k*2];}
}

还有一种一维的写法,不太看得懂,先码吧。

//版本三:一维 dp数组 (下面有和卡哥邏輯一致的一維數組JAVA解法)
class Solution {public int maxProfit(int k, int[] prices) {if(prices.length == 0){return 0;}if(k == 0){return 0;}// 其实就是123题的扩展,123题只用记录2次交易的状态// 这里记录k次交易的状态就行了// 每次交易都有买入,卖出两个状态,所以要乘 2int[] dp = new int[2 * k];// 按123题解题格式那样,做一个初始化for(int i = 0; i < dp.length / 2; i++){dp[i * 2] = -prices[0];}for(int i = 1; i <= prices.length; i++){dp[0] = Math.max(dp[0], -prices[i - 1]);dp[1] = Math.max(dp[1], dp[0] + prices[i - 1]);// 还是与123题一样,与123题对照来看// 就很容易啦for(int j = 2; j < dp.length; j += 2){dp[j] = Math.max(dp[j], dp[j - 1] - prices[i-1]);dp[j + 1] = Math.max(dp[j + 1], dp[j] + prices[i - 1]);}}// 返回最后一次交易卖出状态的结果就行了return dp[dp.length - 1];}
}

遇到的困难

        无

今日收获

        加强了一下二维dp的做法,记住套路吧。

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

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

相关文章

Vector里常用的操作(C++)

1 引言 编程时常用的Vector操作有创建、访问元素、增加元素、删除元素、修改元素、查找索引以及一些常用的函数操作&#xff0c;本文总结了一下这些方法在C里面的实现方式&#xff08;并不是唯一的&#xff09;。 2 创建 操作类别注释C创建创建空向量vector<int>a;创建…

Arduino中增加修改ESP32烧录固件的速度

在Arduino中&#xff0c;默认对ESP32-S3芯片的烧录速度只支持115200、230400、460800、921600这几种速率。只能够在 工具->Upload Speed中选择这些。 有的时候烧录还是觉得太慢了。那么能否更快一些呢&#xff1f; 首先你的USB转串口芯片要支持高速的。常见的芯片速率支持…

Java | 选择排序算法实现

大家可以关注一下专栏&#xff0c;方便大家需要的时候直接查找&#xff0c;专栏将持续更新~ 题目描述 编写一个Java程序&#xff0c;实现选择排序算法。程序需要能够接收一个整型数组作为输入&#xff0c;并输出排序后的数组。 选择排序是一种简单直观的排序算法&#xf…

机械臂模型更换成自己的urdf模块

1.将urdf生成slx文件 smimport(rm_65_flange.urdf);%生成Simscape物理模型 2.更换joint部分&#xff08;对应与几个输入几个输出&#xff09;&#xff08;依次更换&#xff09; 3.更改关节部分&#xff08;依次更换&#xff09; 找到urdf文件夹下的meshes文件夹&#xff0c;看…

electron实现静默打印(各种踩坑解决)

前车之鉴 也是阅读了很多资料和前人踩的坑&#xff0c;直接使用webContent.print方法进行打印。其他方式要不就是Bug多&#xff0c;官方修复也有问题&#xff1b;要不就是官方升级版本后不再支持等 不赘述 需求思路 在main里面实现printerHandle&#xff0c;暴露给渲染线程去…

基于单片机的羽毛球计分器(含proteus仿真和程序)

目录 完整文本及仿真、程序可私信我获取 前言 第一章 设计任务及方案 1.1 设计任务 1.2 总体设计分析 1.3 功能模块方案设计 1.4 方案确定 第二章、硬件设计 2.1 AT89C51 单片机芯片介绍 2.1.1 主要特性 2.1.2 管脚说明 2.1.3 元件清单 2.2 电路介绍 2…

自动化测试用例设计

知人者智&#xff0c;自知者明。大家好&#xff0c;给大家分享一下关于自动化测试用例的设计心得&#xff0c;首先完整的熟悉业务是第一步要做的&#xff0c;不熟悉业务的前提下不会设计出高效且合理的用例&#xff0c;其次是我们要有明确的测试目标&#xff0c;确保我们写的每…

Redis(单/多)线程

一、 Redis 单线程 与 多线程 怎么说&#xff1f; &#xff08;1&#xff09;重要的版本迭代 redis4 之前仅支持 单线程&#xff0c; redis 4之后慢慢 支持多线程&#xff0c; 直到redis6/7后才稳定 &#xff08;2&#xff09;redis 的 工作线程 是 单线程的 &#xff08…

阿里云难题学习笔记

1、下列内存区段增长方是向低地址方向的有&#xff08; &#xff09;&#xff1f; A: 文本段 B: 数据段 C: 堆区 D: 栈区 解析&#xff1a; 在内存管理中&#xff0c;不同的内存区段增长方向是不同的。栈区&#xff08;Stack&#xff09;的增长方向是向低地址方向的&…

Nacos和Eureka有什么区别!!!

一致性模型&#xff1a; Eureka&#xff1a;采用的是 AP&#xff08;Availability, Partition Tolerance&#xff09;模型&#xff0c;即在面临网络分区或部分节点故障时优先保证系统的可用性&#xff0c;牺牲一定的数据一致性。Eureka 通过自我保护机制&#xff0c;允许在节点…

Python构建学生信息管理系统:构建RESTful API - 学生信息管理系统的后端逻辑

在之前的博客里&#xff0c;我们已经完成了项目初始化&#xff0c;在本篇博客中&#xff0c;我们将深入探讨如何使用Flask框架实现学生信息管理系统的后端逻辑&#xff0c;特别是通过RESTful API来实现学生信息的增删改查&#xff08;CRUD&#xff09;操作。 Flask RESTful AP…

go的内存分配机制

Go 语言的内存分配机制可以分为几个主要类别&#xff0c;每个类别都有其特定的行为和优化&#xff1a; 1. 栈&#xff08;Stack&#xff09;分配 局部变量&#xff1a;在函数内部定义的变量通常分配在栈上。大小限制&#xff1a;栈的大小有限&#xff0c;适用于生命周期短、大…

C系统编程:从零手搓一个shell

背景 这么久没更新就是在干这件事&#xff01;&#xff01;因为系统编程已经学的差不多了&#xff0c;所以想找几个项目练练手&#xff0c;之前就一直想写一个自己的shell&#xff01;&#xff01;现在终于有机会实现了。 首先说明一下我的操作系统&#xff1a;Arch linux 服务…

pandas 读取JSON字符串解析长整形丢失数据精度,读取值与实际值不一致

目录 背景&#xff1a; JSON字符串 解析代码 解决方案 背景&#xff1a; 在使用pandas read_json方法读取JSON存为Excel文件时&#xff0c;发现Excel中order_no的值与JSON字符串中的值不一致&#xff0c;开始怀疑是Excel保存精度问题&#xff0c;但是Excel输出实际为字符串…

【OceanBase系列】—— 常用 SQL

作者简介&#xff1a; 花名&#xff1a;绪宁&#xff0c;OceanBase 数据库解决方案架构师 对使用OB过程中常用的一些SQL进行了整理&#xff0c;对应的版本是 4.x。 集群信息 查看版本 show variables like version_comment; 查看集群ID和集群名 show parameters like %clust…

函数的查询

Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 在实际使用中经常会需要查询数据库中已有的函数或者某一个函数的内容&#xff0c;下面就介绍一下如何查询函数。 和存储过程类似&#xff0c;这也需要使用到数据字典user_s…

Spring - 4 ( 11000 字 Spring 入门级教程 )

一&#xff1a;Spring IoC&DI 在前⾯的章节中, 我们学习了 Spring Boot 和 Spring MVC 的开发, 可以完成⼀些基本功能的开发了, 但是什么是 Spring 呢? Spring, Spring Boot 和 SpringMVC 又有什么关系呢? 咱们还是带着问题去学习.我们先看什么是Spring 1.1 Spring 是什…

设计模式学习笔记 - 开源实战四(下):总结Spring中用到的11种设计模式

概述 上篇文章&#xff0c;讲解了 Spring 中支持扩展功能的两种设计模式&#xff1a;观察者模式和模板模式。这两种模式帮助我们创建扩展点&#xff0c;让框架的使用者在不修改源码的情况下&#xff0c;基于扩展点定制化框架功能。 实际上&#xff0c;Spring 框架中用到的设计…

vue项目中定位组件来源的查找思路

vue项目中定位组件来源的查找思路 先去【package.json】里面看看有没有看【a】开头或者【a-】开头的插件名 例如&#xff1a;如果我不知道【el-tree】&#xff0c;先去【package.json】里面找【el】或者【el-】开头的插件名&#xff0c;结果知道了【element-ui】这样就可以直接…

更新至2022年上市公司数字化转型数据合集(四份数据合集)

更新至2022年上市公司数字化转型数据合集&#xff08;四份数据合集&#xff09; 一、2000-2022年上市公司数字化转型数据&#xff08;年报词频、文本统计&#xff09; 二、2007-2022年上市公司数字化转型数据&#xff08;年报和管理层讨论&#xff09;&#xff08;含原始数据…