思路:
本题思路和买卖股票的最佳时机 II一致,都是可以多次购买,累计所获得的金额。稍有不同的地方是,本题增加了一个冷冻期,因此在dp数组中需要增加一个状态来表示冷冻期时所持有的最大金额,并且在递推公式中也和冷冻期有关。
首先定义下标:在第i天,dp[i][[0]表示持有股票的状态下所能获得的最大金额,dp[i][1]表示未持有股票,并且不处于冷冻期的状态下所能获得的最大金额,dp[i][2]表示未持有股票,并且处于冷冻其所能获得的最大金额。然后初始化dp,dp[0][0]表示第一天购买股票,所以dp[0][0] = -prices[0],其他两个状态持有最大金额均为0。
接下来是递推公式,三种状态各需要一个递推公式。
递推公式就是以上三条,然后从i=1遍历prices数组,直到最后一天,因为我们知道未持有股票时的最大金额一定是大于持有股票的,所以我们需要在未持有股票时的两种状态,也就是冷冻期和非冷冻期之间选一个较大的金额作为最终结果,也就是max(dp[prices.size()-1][1], dp[prices.size()-1][2])。
代码:
- class Solution {
- public:
- int maxProfit(vector<int>& prices) {
- if (prices.size() <= 1)
- return 0;
- vector
int>> dp(prices.size(), vector<int>(3)); - // 0:持有 1:未持有 2:冷冻期
- 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] = max(dp[i-1][1], dp[i-1][0] + prices[i]);
- dp[i][2] = dp[i-1][1];
- }
- return max(dp[prices.size()-1][1], dp[prices.size()-1][2]);
- }
- };
思路:
本题和122. 买卖股票的最佳时机 II几乎是一模一样了,除了增加了一个手续费以外,没有冷冻期,也不限制买入次数,所以做法几乎是一样的,递推公式唯一的区别就在,计算未持有股票的价格的时候,卖出股票时加上当天的股票价格prices[i]后,要减掉手续费fee,其他部分代码完全一样。
虽然在没有手续费的时候,这种方法看起来很麻烦,看似不如用贪心法,但是一旦题目变得更加复杂,贪心法的策略也更加难写,但是用动态规划的话就很容易解决了,思路也比较简单。
代码:
- class Solution {
- public:
- int maxProfit(vector<int>& prices, int fee) {
- vector
int>> dp(2, vector<int>(2)); - dp[0][0] = -prices[0];
- for (int i = 1; i < prices.size(); i++)
- {
- dp[i % 2][0] = max(dp[(i-1) % 2][0], dp[(i-1) % 2][1] - prices[i]);
- dp[i % 2][1] = max(dp[(i-1) % 2][1], dp[(i-1) % 2][0] + prices[i] - fee);
- }
- return dp[(prices.size()-1) % 2][1];
- }
- };