本文最后更新于 426 天前,其中的信息可能已经有所发展或是发生改变。
题目描述
- 给定一个数组,它的第
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:
输入: nums = [1,2,3,4,5]
输出: 4
解释: 在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。
因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票
示例3:
输入: nums = [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 交易无法获得正利润,所以不参与交易可以获得最大利润,最大利润为 0。
提示:
- 1 <= prices.length <= 3 * 10^5
- 0 <= prices[i] <= 10^5
解题思路
第i天对股票有以下几种状态:①未持有;②第一次持有;③第一次不持有;④第二次持有;⑤第二次不持有
- 确定dp数组以及下标的含义
dp[i][0]表示第i天未持有股票所得的最多现金
dp[i][1]表示第i天第一次持有股票所得的最多现金=延续前一天第一次持有状态+今天第一次买入未持有
dp[i][2]表示第i天第一次不持有股票所得的最多现金=延续前一天第一次不持有状态+今天卖出前一天第一次持有
dp[i][3]表示第i天第二次持有股票所得的最多现金=延续前一天第二次持有的状态+今天买入第一次持有的股票
dp[i][4]表示第i天第二次不持有股票所得的最多现金=延续前一天第二次不持有状态+今天卖出第二次持有股票 - 递推公式
dp[i][0] = dp[i-1][0]dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i])dp[i][2] = max(dp[i-1][2], dp[i-1][1] + prices[i])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]
- dp数组初始化
dp[0][0] = 0dp[0][1] = -prices[0]dp[0][2] = 0dp[0][3] = -prices[0]dp[0][4] = 0
- 确定遍历顺序 根据递推公式可以看出,
- 打印dp数组
dp[i] 都是由 dp[i-1] 推出来的,那么遍历顺序一定是从前往后遍历。
代码实现
- 核心模式
class Solution{
public:
int maxProfit(vector<int>& prices){
int len = prices.size();
if (len == 0) return 0;
vector<vector<int>> dp(len, vector<int>(5, 0));
// initialize the DP array
dp[0][0] = 0;
dp[0][1] = -prices[0];
dp[0][2] = 0;
dp[0][3] = -prices[0];
dp[0][4] = 0;
for (int i = 1; i < len; i++){
dp[i][0] = dp[i - 1][0];
dp[i][1] = std::max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
dp[i][2] = std::max(dp[i - 1][2], dp[i - 1][1] + prices[i]);
dp[i][3] = std::max(dp[i - 1][3], dp[i - 1][2] - prices[i]);
dp[i][4] = std::max(dp[i - 1][4], dp[i - 1][3] + prices[i]);
}
return dp[len - 1][4];
}
};
- ACM模式
#include <iostream>
#include "dynamicPro.h"
class Solution{
public:
int maxProfit(vector<int>& prices){
int len = prices.size();
if (len == 0) return 0;
vector<vector<int>> dp(len, vector<int>(5, 0));
// initialize the DP array
dp[0][0] = 0;
dp[0][1] = -prices[0];
dp[0][2] = 0;
dp[0][3] = -prices[0];
dp[0][4] = 0;
for (int i = 1; i < len; i++){
dp[i][0] = dp[i - 1][0];
dp[i][1] = std::max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
dp[i][2] = std::max(dp[i - 1][2], dp[i - 1][1] + prices[i]);
dp[i][3] = std::max(dp[i - 1][3], dp[i - 1][2] - prices[i]);
dp[i][4] = std::max(dp[i - 1][4], dp[i - 1][3] + prices[i]);
}
print2DVector(dp);
return dp[len - 1][4];
}
};
int main(){
vector<int> case1 = {3, 3, 5, 0, 0, 3, 1, 4};
vector<int> case2 = {1, 2, 3, 4, 5};
vector<int> case3 = {7, 6, 4, 3, 1};
Solution solution;
cout << "DP Array = " << solution.maxProfit(case1) << endl;
cout << "DP Array = " << solution.maxProfit(case2) << endl;
cout << "DP Array = " << solution.maxProfit(case3) << endl;
return 0;
}
- 输出
DP Array = [[0, -3, 0, -3, 0], [0, -3, 0, -3, 0], [0, -3, 2, -3, 2], [0, 0, 2, 2, 2], [0, 0, 2, 2, 2], [0, 0, 3, 2, 5], [0, 0, 3, 2, 5], [0, 0, 4, 2, 6]]
6
DP Array = [[0, -1, 0, -1, 0], [0, -1, 1, -1, 1], [0, -1, 2, -1, 2], [0, -1, 3, -1, 3], [0, -1, 4, -1, 4]]
4
DP Array = [[0, -7, 0, -7, 0], [0, -6, 0, -6, 0], [0, -4, 0, -4, 0], [0, -3, 0, -3, 0], [0, -1, 0, -1, 0]]
0