LeetCode 0123.买卖股票的最佳时机III:常数空间下的动态规划+模拟
Posted Tisfy
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 0123.买卖股票的最佳时机III:常数空间下的动态规划+模拟相关的知识,希望对你有一定的参考价值。
【LetMeFly】123.买卖股票的最佳时机 III:常数空间下的动态规划+模拟
力扣题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iii/
给定一个数组,它的第 i
个元素是一支给定的股票在第 i
天的价格。
设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例 1:
输入:prices = [3,3,5,0,0,3,1,4] 输出:6 解释:在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,这笔交易所能获得利润 = 3-0 = 3 。 随后,在第 7 天(股票价格 = 1)的时候买入,在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3 。
示例 2:
输入:prices = [1,2,3,4,5] 输出:4 解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。 注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。 因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。
示例 3:
输入:prices = [7,6,4,3,1] 输出:0 解释:在这个情况下, 没有交易完成, 所以最大利润为 0。
示例 4:
输入:prices = [1] 输出:0
提示:
1 <= prices.length <= 105
0 <= prices[i] <= 105
方法一:常数空间下的动态规划
这道题说白了最多有 5 5 5个状态:
- 未进行过任何交易
- 进行了一次买入
- 进行了一次买卖
- 进行了一次买卖 + 一次买入
- 进行了两次买卖
未进行任何交易时,所获利为 0 0 0,因此无需特别关注。
用四个变量 b u y 1 , s e l l 1 , b u y 2 , s e l l 2 buy1, sell1, buy2, sell2 buy1,sell1,buy2,sell2分别代表交易进行到剩下的四种状态时,当前获利的最大值。(这里变量名尽量与官方题解保持一致)
接下来我们严格遵守上述四个变量的含义
将四个变量的初始值赋值为第一天过后的最大获利值:
- b u y 1 buy1 buy1:第一天进行了一次买入。那么当前最大获利为 负的第一天的股价 负的第一天的股价 负的第一天的股价(说是最大获利,其实第一天进行到这种状态的话别无选择,只有这一种获利结果)
- s e l l 1 sell1 sell1:第一天进行了一次买卖。那么买入和卖出的价格相同,当前最大获利为 0 0 0
- b u y 2 buy2 buy2:第一天进行了一次买卖 + 一次买入。也就是说第一天买了一次立刻卖了,然后又买了一次,总(最大)获利为 负的第一天的股价 负的第一天的股价 负的第一天的股价
- s e l l 2 sell2 sell2:第一天进行了两次买卖。总收益为 0 0 0
int buy1 = -prices[0]
int sell1 = 0;
int buy2 = -prices[0]
int sell2 = 0;
接下来,从第 2 2 2天开始,模拟前 i i i天,每种状态下的最大获利。
- b u y 1 buy1 buy1:前 i i i天只进行过一次买入的最大获利。 b u y = max ( b u y ′ , − p r i c e s [ i ] ) buy=\\max(buy', -prices[i]) buy=max(buy′,−prices[i])。也就是说,可以是前 i − 1 i-1 i−1天股价较低的时候进行一次买入( b u y ′ buy' buy′),也可以不在前 i − 1 i-1 i−1天买而是在第 i i i天买入( − p r i c e s [ i ] -prices[i] −prices[i])。(这里用 b u y ′ buy' buy′代表第 i − 1 i-1 i−1天时 b u y buy buy的值)
- s e l l 1 sell1 sell1:前 i i i天进行过一次买卖。 s e l l 1 = max ( s e l l 1 ′ , b u y 1 ′ + p r i c e s [ i ] ) sell1=\\max(sell1', buy1' + prices[i]) sell1=max(sell1′,buy1′+prices[i])。也就是说,可以是在前 i − 1 i-1 i−1天进行了一次买卖而今天不进行任何操作( s e l l 1 ′ sell1' sell1′),也可以是前 i − 1 i-1 i−1天只进行了买入而在第 i i i天卖出( b u y 1 ′ + p r i c e s [ i ] buy1'+prices[i] buy1′+prices[i])(卖出会获利 p r i c e s [ i ] prices[i] prices[i])
- b u y 2 buy2 buy2:前 i i i天进行过一次买卖+一次买入。 b u y 2 = max ( b u y 2 ′ , s e l l 1 ′ − p r i c e s [ i ] ) buy2=\\max(buy2', sell1'-prices[i]) buy2=max(buy2′,sell1′−prices[i])。也就是说,可以是在前 i − 1 i-1 i−1天进行了一次买卖+一次买入而今天不进行任何操作( b u y 2 ′ buy2' buy2′),也可以是前 i − 1 i-1 i−1天进行了一次买卖而在第 i i i天又买入了一次( s e l l 1 ′ + ( − p r i c e s [ i ] ) sell1' + (-prices[i]) sell1′+(−prices[i]))(买入会支出 p r i c e s [ i ] prices[i] prices[i])
- s e l l 2 sell2 sell2:前 i i i天进行了两次买卖。 s e l l 2 = max ( s e l l 2 ′ , b u y 2 ′ + p r i c e s [ i ] ) sell2=\\max(sell2',buy2'+prices[i]) sell2=max(sell2′,buy2′+prices[i])。可以是在前 i − 1 i-1 i−1天进行了两次买卖而今天不进行任何操作( s e l l 2 ′ sell2' sell2′),也可以是前 i − 1 i-1 i−1天只进行了一次买卖+一次买入而在第 i i i天卖出了第二次买入( b u y 2 ′ + p r i c e s [ i ] buy2'+prices[i] buy2′+prices[i])(卖出会获利 p r i c e s [ i ] prices[i] prices[i])
因此,模拟完 n n n天后,返回 s e l l 2 sell2 sell2即可(进行了两次买卖)
注意,题目中是最多进行两次买卖,也就是说可以只进行一次买卖或不进行任何买卖。不进行买卖和买入的当天卖出是等价的,因此可以理解为必须进行了两次买卖但可能买入的同一天卖出过。
- 时间复杂度 O ( n ) O(n) O(n)
- 空间复杂度 O ( 1 ) O(1) O(1),只使用了常数个额外空间
AC代码
C++
class Solution
public:
int maxProfit(vector<int>& prices)
int buy1 = -prices[0], sell1 = 0;
int buy2 = -prices[0], sell2 = 0;
for (int i = 1; i < prices.size(); i++)
buy1 = max(buy1, 0 + (-prices[i]));
sell1 = max(sell1, buy1 + (prices[i]));
buy2 = max(buy2, sell1 + (-prices[i]));
sell2 = max(sell2, buy2 + (prices[i]));
return sell2;
;
代码很短,关键在于严格遵守变量的定义并理解。
同步发文于CSDN,原创不易,转载请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/125889831
以上是关于LeetCode 0123.买卖股票的最佳时机III:常数空间下的动态规划+模拟的主要内容,如果未能解决你的问题,请参考以下文章
LeetCode | 0123. Best Time to Buy and Sell Stock III买卖股票的最佳时机 IIIPython