Leetcode 123.买卖股票的最佳时机III
题目链接: Leetcode 123.买卖股票的最佳时机III
题目描述: 给定一个数组,它的第 i
个元素是一支给定的股票在第 i
天的价格。设计一个算法来计算你所能获取的最大利润。你最多可以完成两笔交易。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
思路: 由于交易次数不确定,因此不像Leetcode 121. 买卖股票的最佳时机和Leetcode 122.买卖股票的最佳时机II这两道题可以利用贪心思想解决,本题只能通过动态规划不断记录最大利润来解决。
dp
数组有五种状态:
- 没有操作 (也可以不设置这个状态)
- 第一次持有股票
- 第一次不持有股票
- 第二次持有股票
- 第二次不持有股票
- 递推公式:无论哪种状态,都取决于第
i
天是否买卖股票两种状态。理解了之前买卖股票两道题的递推公式就会更好理解一些 - 初始化:
dp[0][1] = dp[0][3] = -prices[0]
代码如下:
class Solution {
public:
int maxProfit(vector<int>& prices) {
if(prices.size() == 0) return 0;
//dp[i][0]:不进行操作
//dp[i][1]:第一次买入
//dp[i][2]:第一次卖出
//dp[i][3]:第二次买入
//dp[i][4]:第二次卖出
vector<vector<int>> dp(prices.size(), vector<int>(5, 0));
//初始化
dp[0][1] = dp[0][3] = -prices[0];
for(int i = 1; i < prices.size(); i ++ )
{
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]);
}
return dp[prices.size() - 1][4];
}
};
- 时间复杂度: O ( n ) O(n) O(n)
- 空间复杂度: O ( 5 × n ) O(5×n) O(5×n) (严格的空间复杂度不用写系数,这里是为了体现 5 5 5种状态)
Leetcode 188.买卖股票的最佳时机IV
题目链接:Leetcode 188.买卖股票的最佳时机IV
题目描述: 给定一个数组,它的第 i
个元素是一支给定的股票在第 i
天的价格。设计一个算法来计算你所能获取的最大利润。你最多可以完成k
笔交易。 也就是说,你最多可以买 k
次,卖 k
次。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
思路: 本题与上道题相比,从最多两次交易变成最多k
次交易,大体思路是相同的,唯一的区别就在于初始化和dp运算。
代码如下:
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
int n = prices.size();
if(n == 0) return 0;
//dp[i][奇数]代表买入,dp[i][偶数]代表卖出
vector<vector<int>> dp(n, vector<int>(2 * k + 1, 0));
//初始化
for(int i = 1; i < 2 * k; i +=2 ){
dp[0][i] = -prices[0];
}
for(int i = 1; i < n; i ++ )
for(int j = 0; j <= 2 * k - 1; j += 2)
{
//奇数买入
dp[i][j + 1] = max(dp[i - 1][j + 1],dp[i - 1][j] - prices[i]);
//偶数卖出
dp[i][j + 2] = max(dp[i - 1][j + 2],dp[i - 1][j + 1] + prices[i]);
}
return dp[n - 1][2 * k];
}
};
- 时间复杂度:
O
(
n
×
k
)
O(n ×k)
O(n×k),其中
n
为prices
的长度 - 空间复杂度: O ( n × k ) O(n × k) O(n×k)
总结: 理解了之前两道买卖股票的递推公式原理,这两道题还是很简单的。
最后,如果文章有错误,请在评论区或私信指出,让我们共同进步!