123. 买卖股票的最佳时机 III
题目大意:给定n天股票的价格,你可以选择买入卖出的时机,但是同一时间只能最多拥有一支股票,且最多买卖两次,求最后获得的最大利润
解题思路:可以参照股票2的解法,仅仅加上了一个交易次数的限制,再dp[i][j] 的基础上再加一个参与控制次数 及dp[i][j][k] 表示第i天再股票持有状态为j,且当前买卖了k次的最大利润。以此可以推出状态转移方程。
ps:需要注意的点是 交易次数跟天数挂钩,第i天的交易次数为 (i+1)/2,所以再前面几天 有的k[0,2]值是空着的 为了保证整个过程中k的值都是由前面正确操作买入卖出转移过来 我们需要把数组初始化为-inf。
1 class Solution { 2 public: 3 int maxProfit(vector<int>& prices) { 4 int iSize = prices.size(); 5 const int maxn = 1e5+10; 6 int dp[maxn][2][3]; 7 memset(dp,128,sizeof(dp)); 8 dp[0][0][0] = 0; 9 dp[0][1][0] = -prices[0]; 10 for(int i = 1; i < iSize; ++i) 11 { 12 dp[i][0][0] = dp[i-1][0][0]; 13 dp[i][0][1] = max(dp[i-1][1][0] + prices[i], dp[i-1][0][1]); 14 dp[i][0][2] = max(dp[i-1][1][1] + prices[i], dp[i-1][0][2]); 15 dp[i][1][0] = max(dp[i-1][0][0] - prices[i], dp[i-1][1][0]); 16 dp[i][1][1] = max(dp[i-1][0][1] - prices[i], dp[i-1][1][1]); 17 dp[i][1][2] = max(dp[i-1][0][2], dp[i-1][1][2]); 18 } 19 int ans = 0; 20 ans = max(ans ,dp[iSize-1][0][0]); 21 ans = max(ans ,dp[iSize-1][0][1]); 22 ans = max(ans ,dp[iSize-1][0][2]); 23 return ans; 24 } 25 };
股票四:限制2->k即可,将(0,k) 之间的写入for循环 用状态转移方程填充,0,k两个单独处理即可
1 class Solution { 2 public: 3 int maxProfit(int k, vector<int>& prices) { 4 if(k == 0 || prices.size() == 0)return 0; 5 int iSize = prices.size(); 6 int dp[iSize+1][2][k+1]; 7 memset(dp,128,sizeof(dp)); 8 dp[0][0][0] = 0; 9 dp[0][1][0] = -prices[0]; 10 for(int i = 1; i < iSize; ++i) 11 { 12 dp[i][0][0] = dp[i-1][0][0]; 13 dp[i][1][0] = max(dp[i-1][0][0] - prices[i], dp[i-1][1][0]); 14 for(int j = 1; j < k; ++j) 15 { 16 dp[i][0][j] = max(dp[i-1][1][j-1] + prices[i], dp[i-1][0][j]); 17 dp[i][1][j] = max(dp[i-1][0][j] - prices[i], dp[i-1][1][j]); 18 } 19 dp[i][0][k] = max(dp[i-1][1][k-1] + prices[i], dp[i-1][0][k]); 20 dp[i][1][k] = max(dp[i-1][0][k], dp[i-1][1][k]); 21 } 22 int ans = 0; 23 for(int i = 0; i <= k; ++i) 24 ans = max(ans ,dp[iSize-1][0][i]); 25 return ans; 26 } 27 };