1、动态规划法
我们可以使用数组dp记录每天买卖股票可以获得的最大利润,其中针对买卖股票的不同状态有三种情况:1、我们拥有股票但未卖出,此时我们可能是从两种状态转移来的,一是前一天也持有未售出的股票;二是前一天刚刚结束未持有股票的状态,并刚刚购买了股票,因此为了获得当前的最大利润,我们可以得到状态转移公式为 d p [ i ] [ 0 ] = m a x ( d p [ i − 1 ] [ 0 ] , d p [ i − 1 ] [ 2 ] − p r i c e s [ i ] ) dp[i][0] = max(dp[i - 1][0], dp[i - 1][2] - prices[i]) dp[i][0]=max(dp[i−1][0],dp[i−1][2]−prices[i]);2、我们未持有股票并处于冷冻期,此时我们只有可能是从一种状态转移过来的,就是前一天刚刚出售了股票,我们可以得到状态转移公式为 d p [ i ] [ 1 ] = d p [ i − 1 ] [ 0 ] + p r i c e s [ i ] dp[i][1] = dp[i - 1][0] + prices[i] dp[i][1]=dp[i−1][0]+prices[i];3、我们未持有股票并不处于冷冻期,此时我们可能是从两种状态转移过来的:一是我们昨天处于冷冻期;二是我们昨天也没有持有股票,我们可以得到状态转移公式为 d p [ i ] [ 2 ] = m a x ( d p [ i − 1 ] [ 1 ] , d p [ i − 1 ] [ 2 ] ) dp[i][2] = max(dp[i - 1][1], dp[i - 1][2]) dp[i][2]=max(dp[i−1][1],dp[i−1][2])。最终我们为了获得最大利润,只需要比较 d p [ p r i c e s . s i z e ( ) − 1 ] [ 1 ] , d p [ p r i c e s . s i z e ( ) − 1 ] [ 2 ] dp[prices.size() - 1][1], dp[prices.size() - 1][2] dp[prices.size()−1][1],dp[prices.size()−1][2]中的最大值即可。
class Solution {
public:
int maxProfit(vector<int> &prices) {
if (prices.size() == 0 || prices.size() == 1) return 0;
vector<vector<int>> dp(prices.size(), vector<int>(3, 0));
dp[0][0] = -prices[0];
for (int i = 1; i < prices.size(); ++i) {
dp[i][0] = max(dp[i - 1][0], dp[i - 1][2] - prices[i]);
dp[i][1] = dp[i - 1][0] + prices[i];
dp[i][2] = max(dp[i - 1][1], dp[i - 1][2]);
}
return max(dp[prices.size() - 1][1], dp[prices.size() - 1][2]);
}
};
2、动态规划法优化
考虑到我们虽然占用了一个二维数组,但我们实际上使用的只有昨天的最大利润,因此我们可以使用三个变量来代替二维数组。
class Solution {
public:
int maxProfit(vector<int> &prices) {
if (prices.size() == 0 || prices.size() == 1) return 0;
int profit_1 = -prices[0];
int profit_2 = 0;
int profit_3 = 0;
for (int i = 1; i < prices.size(); ++i) {
int temp_profit_1 = max(profit_1, profit_3 - prices[i]);
int temp_profit_2 = profit_1 + prices[i];
int temp_profit_3 = max(profit_2, profit_3);
profit_1 = temp_profit_1;
profit_2 = temp_profit_2;
profit_3 = temp_profit_3;
}
return max(profit_2, profit_3);
}
};