一天一大 leet(最佳买卖股票时机含冷冻期)难度:中等-Day20200710
时间:2022-07-25
本文章向大家介绍一天一大 leet(最佳买卖股票时机含冷冻期)难度:中等-Day20200710,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
题目:
给定一个整数数组,其中第 i 个元素代表了第 i 天的股票价格 。
设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
- 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
- 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
示例
输入: [1,2,3,0,2]
输出: 3
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]
抛砖引玉
- 第一天收益设置为 -prices[0],作为成本(即成本也纳入收益计算)
- 第 i 天价格为 prices[i]
- 冷冻期 如果这一天为冷冻期说明为前一天卖出,则这一天的收益为:
- 前一天持有时的最大收益+卖出的盈利
- dp[i-1][持有] + prices[i]
- 不持有 如果这一天不持有则前一天可能是不持有或者为冷冻期(一定不是持有),则这一天收益理论上不变沿用前一天的收益,计算收益最大则取两周可能中较大的收益 max:max(dp[i-1][不持有], dp[i-1][冷冻])
-
持有 如果这一天为持有,则前一天可能是持有也可能为不持有(一定不是冷冻),则这一天收益:
- 注意 前一天如果为不持有则说明今天买入后才持有则按照计入成本规则需要减掉今日的成本
- max(前一天持有时的最大收益, 前一天不持有时的最大收益-今日成本)
-
max(dp[i-1][持有], dp[i-1][不持有]-prices[i])
示例:[1,2,3,0,2]
最后如果计算收益最大,则结束时状态不能为持有
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function (prices) {
let len = prices.length,
dp = Array(len)
// prices小于2是买入来不及卖出
if (len < 2) return 0
// 初始化存储对象
for (let i = 0; i < len; i++) {
dp[i] = [0, 0, 0]
}
// 初始化成本
dp[0][0] = -prices[0]
for (let i = 1; i < len; i++) {
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][2] - prices[i])
dp[i][1] = dp[i - 1][0] + prices[i]
dp[i][2] = Math.max(dp[i - 1][1], dp[i - 1][2])
}
return Math.max(dp[len - 1][1], dp[len - 1][2])
}
优化:
- 存储降维
- 从上面的逻辑可以发现当 i 递增时,计算当前 i 的不同状态收益只需要 i-1 不同状态收益
- 那可以声明一个中间变量来存贮 i-1 的状态就可以替代 dp 的作用了
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function (prices) {
let len = prices.length
// prices小于2是买入来不及卖出
if (len < 2) return 0
// 初始化存储对象
let A = -prices[0],
B = 0,
C = 0
// 初始化成本
for (let i = 1; i < len; i++) {
let a = Math.max(A, C - prices[i])
let b = A + prices[i]
let c = Math.max(B, C)
A = a
B = b
C = c
}
return Math.max(B, C)
}
- 状态归纳
- 0 -> 持有
- 1 -> 冷冻期
- 2 -> 不持有
可以归纳为:
- 0 -> 持有 hold
- 1 -> 不持有(不持有,冷冻期) unhold
持有:
- 第一天成本 -prices[0]
- i=1 第二天持有,有两种可能(前一天不存在持有冷冻情况):
- 第一天买入:hold[i - 1] 及 -prices[0]
- 第二天买入:hold[i - 1] -prices[1],-prices[0]-prices[1]
- i 大于 1 持有时(前一天存在持有冷冻情况):
- 为冷冻,则说明第 i-2 天卖出,第 i 天买入,第 i-2 天不持有的收益减去第 i 天买入的成本:unhold[i - 2]-prices[i]
- 不为冷冻,则最近的一次最大收益应为 hold[i - 2]小于 hold[i - 1]忽略
不持有:
- 第 n-1 天有两种可能:
- 持有,今天不持有卖出今天的价格算入收益:hold[i - 1] + prices[i]
- 不持有,无操作, 其最大收益保持不变
/**
* @param {number[]} prices
* @return {number}
*/
var maxProfit = function (prices) {
let len = prices.length
// prices小于2是买入来不及卖出
if (len < 2) return 0
let hold = Array(len),
unhold = Array(len)
// 初始化存储对象
hold[0] = -prices[0]
unhold[0] = 0
for (let i = 1; i < len; i++) {
if (i == 1) {
hold[i] = Math.max(-prices[0], -prices[1])
} else {
hold[i] = Math.max(hold[i - 1], unhold[i - 2] - prices[i], unhold[i - 1])
}
unhold[i] = Math.max(unhold[i - 1], hold[i - 1] + prices[i])
}
return unhold[len - 1]
}
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 设计模式-从你的日常理解模板方法
- 设计模式-组装电脑入门简单工厂
- 搭建属于自己的FRP内网穿透
- 线上千万级大表排序该如何优化?
- LeetCode-7.整数反转 取模反转法与字符串法
- Spring Bean依赖
- Spring事务是如何应用到你的业务场景中的?
- MySQL8.0大表秒加字段,是真的吗?
- 大数据简介,技术体系分类整理
- 图像处理笔记(5)---- OpenCV 用滑动条做调色板
- 牛X | 一款比传统数据库快100-1000倍的数据库,认识一下
- SpringBoot统一参数校验
- SpringBoot多邮件源发送邮件
- 一个基础的SpringBoot项目该包含哪些
- leetcode树之平衡二叉树