目录
LeetCode 188. 买卖股票的最佳时机 IV
LeetCode 309. 买卖股票的最佳时机含冷冻期
LeetCode 714. 买卖股票的最佳时机含手续费。
总结
LeetCode 188. 买卖股票的最佳时机 IV
题目链接:LeetCode 188. 买卖股票的最佳时机 IV
思想:本题跟之前的买卖股票的最佳时机 III 特别像,本题是把两次交易改为可以有k次交易。那么本题的状态就有2*k+1种,其中一种是什么动作都不采取,剩余2k个状态分别是第i次持有股票,第i次不持有股票。关于dp数组的五部曲都是跟III特别像,dp数组,dp[i][j]就是第i天的第j种状态下的最大利润。初始化就是把所有初次持有股票的状态最大利润初始化为-prices[0]。而持有股票的递推公式就是dp[i][j] = max(dp[i-1][j], dp[i][j-1] - prices[i]),不持有股票的递推公式是dp[i][j] = max(dp[i-1][j], dp[i][j-1] + prices[i])。
代码如下:
int maxProfit(int k, vector<int>& prices) {
vector<vector<int>> dp(prices.size(), 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 < prices.size(); i++) {
for (int j = 0; j < 2 * k - 1; j+=2) {
dp[i][j+1] = max(dp[i-1][j+1], dp[i][j] - prices[i]);
dp[i][j+2] = max(dp[i-1][j+2], dp[i][j+1] + prices[i]);
}
}
return dp[prices.size()-1][2*k];
}
时间复杂度:O(n^2),空间复杂度:O(n^2)。
LeetCode 309. 买卖股票的最佳时机含冷冻期
题目链接:LeetCode 309. 买卖股票的最佳时机含冷冻期
思想:我感觉本题比上一题还要难一点,结果这题标的难度是中等,上一题是困难,没有办法理解。而难就难在讨论递推公式,因为又加了一个规定,买卖股票后的一天无法做任何操作。
这里的状态我本来也是列的三个,结果一看题解是四个,也是跟着大佬的思路来了。
「今天卖出股票」我是没有单独列出一个状态的归类为「不持有股票的状态」,而本题为什么要单独列出「今天卖出股票」 一个状态呢?
因为本题我们有冷冻期,而冷冻期的前一天,只能是 「今天卖出股票」状态,如果是 「不持有股票状态」那么就很模糊,因为不一定是 卖出股票的操作。
那么本题最重要的就是确定递推公式了,要确定每个状态的递推公式。
第一个就是买入状态也就是持有股票状态,首先就是前几天已经买了股票,没有卖出,也就是dp[i][0] = dp[i-1][0]。其次就是今天买入了,有两种情况,前一天是冷冻期买入,前一天未持有股票买入,也就是dp[i][0] = dp[i-1][3] - prices[i] 或 dp[i-1][1] - prices[i]。这三个取最大就行了。
第二个就是卖出状态也就是不持有股票状态,首先就是前几天就不持有股票,没有买入,也就是dp[i][1] = dp[i-1][1]。其次就是今天卖出了股票,即dp[i][1] = dp[i-1][0] + prices[i]。这俩取最大了。
第三个就是今日卖出股票,很简单,dp[i][2] = dp[i-1][0] + prices[i]。
第四个就是冷冻期,也很简单,dp[i][3] = dp[i-1][2]。
其他的所有东西跟之前做过的基本上都一样。
代码如下:
int maxProfit(vector<int>& prices) {
if (prices.size() == 0) return 0;
vector<vector<int>> dp(prices.size(), vector<int> (4, 0));
dp[0][0] = -prices[0];
for (int i = 1; i < prices.size(); i++) {
dp[i][0] = max(dp[i-1][0], max(dp[i-1][3] - prices[i], dp[i-1][1] - prices[i]));
dp[i][1] = max(dp[i-1][1], dp[i-1][3]);
dp[i][2] = dp[i-1][0] + prices[i];
dp[i][3] = dp[i-1][2];
}
return max(dp[prices.size()-1][3], max(dp[prices.size()-1][1],dp[prices.size()-1][2]));
}
时间复杂度:O(n),空间复杂度:O(n^2)。
LeetCode 714. 买卖股票的最佳时机含手续费。
题目链接:LeetCode 714. 买卖股票的最佳时机含手续费
思想:本题其实特别简单,只要在持有递推公式的基础上,加一个-fee就行了。
代码如下:
int maxProfit(vector<int>& prices, int fee) {
vector<vector<int>> dp(prices.size(), vector<int>(2, 0));
dp[0][0] = -prices[0] - fee;
for (int i = 1; i < prices.size(); i++) {
dp[i][0] = max(dp[i-1][0], dp[i-1][1] - prices[i] - fee);
dp[i][1] = max(dp[i-1][1], dp[i-1][0] + prices[i]);
}
return dp[prices.size() - 1][1];
}
时间复杂度:O(n),空间复杂度:O(n^2)。
总结
这么几天练下来,还是没啥感觉,动归还是太难了。