当前位置: 首页 > news >正文

阿里 代码随想录 188.买卖股票的最佳时机Ⅳ

思路:本题要求至多有k次交易。

动规五部曲:

1.确定dp数组以及下标的含义:

(1)dp[i][j]表示第i天的状态为j,所剩下的最大现金为dp[i][j]。

(2)j的状态表示为:

——0表示不操作;

——1表示第一次买入;

——2表示第一次卖出;

——3表示第二次买入;

——4表示第二次卖出;

(3)发现规律:除了0以外,偶数就是卖出,奇数就是买入

(4)题目要求至多有k笔交易,那么j的范围就定义为2*k+1

2.确定递推公式:

(1)注意:dp[i][1]表示的是第i天买入股票的状态,并不是说一定要第i天买入股票。

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

——第i天买入股票了,那么dp[i][1] = dp[i - 1][0] - prices[i]

——第i天没有操作,而是沿用前一天买入的状态,即dp[i][1] = dp[i - 1][1]

——选最大的,所以dp[i][1] = max(dp[i - 1][0] - prices[i],dp[i - 1][1])

(3)同理dp[i][2]也有两个具体操作

——第i天卖出股票了,那么dp[i][2] = dp[i - 1][1] + prices[i]

——第i天没有操作,而是沿用前一天卖出的状态,即dp[i][2] = dp[i - 1][2]

——选最大的,所以dp[i][2] = max(dp[i - 1][1] + prices[i],dp[i - 1][2])

(4)同理可类比剩下的状态,代码如下:

for (int j = 0; j < 2 * k - 1; j += 2) { dp[i][j + 1] = max(dp[i - 1][j + 1], dp[i - 1][j] - prices[i]); dp[i][j + 2] = max(dp[i - 1][j + 2], dp[i - 1][j + 1] + prices[i]); }

3.dp数组如何初始化:

(1)如果第0天没有操作,那就是0。即dp[0][0] = 0。

(2)如果第0天做第一次买入的操作,则dp[0][1] = -prices[0]

(3)如果第0天做第一次卖出的操作,则就是当天买入当天卖出,dp[0][2] = 0。

(4)如果第0天做第二次买入的操作,就是当天买入当天卖出后,再买入一次,dp[0][3] = -prices[0]

(5)同理第二次卖出初始化为dp[0][4] = 0。

(6)同理可推出dp[0][j]:当j为奇数的时候都初始化为-prices[0],代码如下所示:

for (int j = 1; j < 2 * k; j += 2) { dp[0][j] = -prices[0]; }

4.确定遍历顺序:一定是从前向后遍历,因为dp[i]依靠dp[i - 1]的数值。

5.举例推导dp数组:以输入[1,2,3,4,5],k = 2为例。最后一次卖出,一定是利润最大的,dp[prices.size() - 1][2*k],即红色部分,就是最后求解。

附代码:

(一)二维dp数组

class Solution { public int maxProfit(int k, int[] prices) { int len = prices.length; if(len == 0){ return 0; } // [天数][股票状态] // 股票状态:奇数表示第k次交易持有/买入;偶数表示第k次交易不持有/卖出,0表示没有操作 int[][] dp = new int[len][k * 2 + 1]; // dp数组的初始化 for(int j = 1;j < k * 2;j += 2){ dp[0][j] = -prices[0]; } for(int i = 1;i < len;i++){ // j的范围是1到2k的闭区间 // 且j为奇数时表示买入,j为偶数时表示卖出 // 因此j从0开始,j + 1表示奇数,j + 2表示偶数,且两个两个遍历:j += 2 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数组

class Solution { public int maxProfit(int k, int[] prices) { if(prices.length == 0){ return 0; } if(k == 0){ return 0; } //记录k次交易的状态即可 //每次交易都有买入、卖出两个状态,所以要乘2 int[] dp = new int[2 * k]; //dp[0]代表第一次交易的买入 //dp[1]代表第一次交易的卖出 //dp[2]代表第二次交易的买入 //dp[3]代表第二次交易的卖出 for(int i = 0;i < dp.length/2;i++){ dp[i * 2] = -prices[0]; } for(int i = 1;i <= prices.length;i++){ //初始化dp[0]和dp[1] dp[0] = Math.max(dp[0], -prices[i - 1]); dp[1] = Math.max(dp[1],dp[0] + prices[i - 1]); 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]); } } //dp[dp.length - 1]代表完成第k次交易后不持有的最大利润,正是所求值 //求的是利润,不是价格,不能用prices return dp[dp.length - 1]; } }

ACM模式:

import java.util.Scanner; class Solution { public int maxProfit(int k, int[] prices) { int len = prices.length; if (len == 0) { return 0; } // [天数][股票状态] // 股票状态:奇数表示第k次交易持有/买入;偶数表示第k次交易不持有/卖出,0表示没有操作 int[][] dp = new int[len][k * 2 + 1]; // dp数组的初始化 for (int j = 1; j < k * 2; j += 2) { dp[0][j] = -prices[0]; } for (int i = 1; i < len; i++) { // j的范围是1到2k的闭区间 // 且j为奇数时表示买入,j为偶数时表示卖出 // 因此j从0开始,j + 1表示奇数,j + 2表示偶数,且两个两个遍历:j += 2 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]; } } public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); // 读取最大交易次数k int k = scanner.nextInt(); // 读取数组长度 int n = scanner.nextInt(); // 读取价格数组 int[] prices = new int[n]; for (int i = 0; i < n; i++) { prices[i] = scanner.nextInt(); } // 计算最大利润(最多k次交易) Solution solution = new Solution(); int result = solution.maxProfit(k, prices); System.out.println(result); scanner.close(); } }
http://www.jsqmd.com/news/755785/

相关文章:

  • ComfyUI-Impact-Pack:AI图像细节优化的终极完整指南
  • 2026年WCA物流公司推荐:行业优质服务机构盘点 - 品牌排行榜
  • 2026年AI降重效率究竟如何?4款AI工具亲测揭晓答案! - 降AI实验室
  • 2026年横机针多少钱,嘉兴市九九贸易有答案 - mypinpai
  • 开源AI对话平台Stellar-Chat:自托管部署与多模型接入实战
  • 光子集成电路制造中的逆向设计与PRISM技术突破
  • 终端AI助手pilot-shell:用Shell脚本集成LLM提升命令行效率
  • 双向电流分流监控器原理与电机控制应用
  • Go语言分布式任务编排引擎Conductor:轻量级工作流设计与实战
  • 2026国内物流专业公司选择指南:服务与资质深度解析 - 品牌排行榜
  • .NET 9 + Docker一键上线:从零构建高可用API容器的5步极简工作流
  • 阿里巴巴开源RISC-V玄铁处理器核心解析与应用
  • 千问 LeetCode 2081.K 镜像数字的和 TypeScript实现
  • Phi-4-mini-flash-reasoning企业实操:技术文档结构化分析与摘要生成
  • 2026年性价比高的集成房屋定制,靠谱品牌大盘点 - mypinpai
  • D2DX:让经典《暗黑破坏神2》在现代PC上重获新生的终极方案
  • FilePizza终极突破:浏览器P2P文件传输的革命性重构
  • FPGA学习记录----二选一多路选择器
  • AI编码扩展实战指南:四大维度解析与VSCode神装清单
  • 【QuecOpen 实战-006】FreeRTOS 多任务编程实战
  • SIMD指令在Java中的应用探索
  • 从C++主流标准到Qt的版本支持:一位开发者的现实指南
  • find-skills-x:基于代码分析的开源技能发现与匹配工具
  • 基于MediaPipe的Android实时AI视觉应用开发实战
  • 2026年上海专门处理经济纠纷的本地律师排名 - mypinpai
  • Magpie:多模态大模型数据格式对齐工具实战指南
  • (118页PPT)新版VDAFMEA第五版培训(附下载方式)
  • Rust + PostgreSQL 极简技术栈应用开发
  • 【深度解析】Pi 极简终端 Coding Agent:为什么 4 个工具反而更适合 AI 编程?
  • MotionEdit:基于神经场技术的运动数据高效编辑方案