一、题目描述
- 给定一个整数数组
prices,它的第i个元素prices[i]是一支给定的股票在第i天的价格。 - 设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票):
- 卖出股票后,你无法在第二天买入股票 (即冷冻期为
1天)。 - 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
- 卖出股票后,你无法在第二天买入股票 (即冷冻期为
示例:
| 输入 | 输出 | 解释 |
|---|---|---|
| prices = [1,2,3,0,2] | 3 | 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出] |
| prices = [1] | 0 | 买即亏,最大利润为 0 |
提示:
- 0 < = p r i c e s . l e n g t h < = 5000 0 <= prices.length <= 5000 0<=prices.length<=5000
- 0 < = p r i c e s [ i ] < = 1000 0 <= prices[i] <= 1000 0<=prices[i]<=1000
二、求解思路:动态规划(含内存优化python代码)
- 沿用 123 - 买卖股票的最佳时机 III 的超超超通俗易懂的三维动态规划思路,再进行简化状态,优化内存。
- 此时的
dp[i][j][k]的第三维表示是否处于冷冻期,是则为1,不是则为0。 - 分析可知只有四种状态,但有一种状态不可能存在:
dp[i][0][0]表示第i天操作后未持股且未处于冷冻期,即一定是上一天未持股,无论是处于还是未处于冷冻期都有可能,因为冷冻期只能维持一天。并且,上一天不可能持股,是因为如果上一天持股今天未持股,那必定是今天卖了股票,会处于冷冻期;dp[i][0][1]表示第i天操作后未持股且处于冷冻期,即一定是上一天持股到今天卖了的情况;dp[i][1][0]表示第i天操作后持股且未处于冷冻期;dp[i][1][1]表示第i天操作后持股且处于冷冻期,不存在此状态,因为股票无论是今天买的还是之前买的,都不可能买完后处于冷冻期;
- 由此确定状态转移函数:
dp[i][0][1] = max(dp[i-1][0][0], dp[i-1][0][1])dp[i][0][1] = dp[i-1][1][0] + prices[i]dp[i][1][0] = max(dp[i-1][1][0], dp[i-1][0][0] - prices[i])
- 由以上的思路可简化状态,且优化内存,本文尚且提供一个优化的 python 代码。
C++代码
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
int dp[n][2][2];
dp[0][0][0] = 0; dp[0][1][0] = -prices[0]; dp[0][0][1] = 0;
for(int i = 1; i < n; i++) {
dp[i][0][0] = max(dp[i-1][0][0],dp[i-1][0][1]);
dp[i][0][1] = dp[i-1][1][0] + prices[i];
dp[i][1][0] = max(dp[i-1][0][0]-prices[i],dp[i-1][1][0]);
}
return max(dp[n-1][0][0],dp[n-1][0][1]);
}
};

Python3代码
class Solution:
def maxProfit(self, prices: List[int]) -> int:
n = len(prices)
dp = [[[0,0],[0,0]] for i in range(n)]
dp[0][0][0] = 0
dp[0][1][0] = -prices[0]
dp[0][0][1] = 0
for i in range(1,n):
dp[i][0][0] = max(dp[i-1][0][0],dp[i-1][0][1])
dp[i][0][1] = dp[i-1][1][0]+prices[i]
dp[i][1][0] = max(dp[i-1][0][0]-prices[i],dp[i-1][1][0])
return max(dp[n-1][0][0],dp[n-1][0][1])

Java代码
class Solution {
public int maxProfit(int[] prices) {
int n = prices.length;
int[][][] dp = new int[n][2][2];
dp[0][0][0] = 0; dp[0][1][0] = -prices[0]; dp[0][0][1] = 0;
for(int i = 1; i < n; i++) {
dp[i][0][0] = Math.max(dp[i-1][0][0],dp[i-1][0][1]);
dp[i][0][1] = dp[i-1][1][0]+prices[i];
dp[i][1][0] = Math.max(dp[i-1][0][0]-prices[i],dp[i-1][1][0]);
}
return Math.max(dp[n-1][0][0],dp[n-1][0][1]);
}
}

复杂度分析
- 时间复杂度: O ( n ) O(n) O(n)。
- 空间复杂度: O ( n ) O(n) O(n)。
优化内存版本的Python3代码
class Solution:
def maxProfit(self, prices: List[int]) -> int:
n = len(prices)
s0, s1, s2 = -prices[0], 0, 0
for i in range(1, n):
news0 = max(s0, s2 - prices[i])
news1 = s0 + prices[i]
news2 = max(s1, s2)
s0, s1, s2 = news0, news1, news2
return max(s1, s2)

复杂度分析
- 时间复杂度: O ( n ) O(n) O(n)。
- 空间复杂度: O ( 1 ) O(1) O(1)。
三、参考文章
[1] https://blog.csdn.net/qq_40430360/article/details/124760973
228

被折叠的 条评论
为什么被折叠?



