題目來源
Say you have an array for which the ith element is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete at most k transactions.
Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
這道題呢,大家肯定一看也知道應該用DP,但是具體應該怎么用呢,肯定是個二維的DP。假設dp[k][i]
表示前i天里交易k次最大盈利,那么dp[k][i]可以有兩種可能,一種是在第i天的時候沒有交易則dp[k][i] = dp[k][i-1]
,另一種是在第i天的時候有交易則dp[k][i] = dp[k-1][j-1] + price[i] - price[j]
,j表示上一次買入的時候的那一天。
那么dp[k][i] = max(dp[k][i-1], dp[k-1][j-1] + price[i] - price[j])
。
dp[0][i] = 0
因為0次交易的話盈利肯定是0。
dp[k][0] = 0
因為第0天肯定也沒有盈利。
代碼如下所示:
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
int n = prices.size();
vector<vector<int>> dp(k+1, vector<int>(n+1, 0));
for (int i=1; i<=k; i++) {
for (int j=1; j<=n; j++) {
int tmp = 0;
for (int jj=1; jj<j; jj++)
tmp = max(tmp, dp[i-1][jj-1] + prices[j-1] - prices[jj-1]);
dp[i][j] = max(dp[i][j-1], tmp);
}
}
return dp[k][n];
}
};
然后結(jié)果怎么樣,沒錯,又是TLE!又超時了!時間復雜度有點高,O(n^3)。
然后參考了下大神的,修改了一下代碼,改成O(n^2)的。
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
int n = prices.size();
if (n < 2)
return 0;
int maxPro = 0;
vector<vector<int>> dp(k+1, vector<int>(n+1, 0));
for (int i=1; i<=k; i++) {
int tmpMax = dp[i-1][1] - prices[0];
for (int j=1; j<=n; j++) {
dp[i][j] = max(dp[i][j-1], tmpMax + prices[j-1]);
tmpMax = max(tmpMax, dp[i-1][j] - prices[j-1]);
maxPro = max(maxPro, dp[i][j]);
}
}
return maxPro;
}
};
巧妙的引入了一個tmpMax來存儲以前dp[i-1][jj-1] + prices[j-1] - prices[jj-1]
中的dp[i-1][jj-1] - prices[jj-1]
。
但是還是A不了,當k或者prices非常大的時候,內(nèi)存溢出了。
繼續(xù)看看怎么改進,可以采取一些小技巧來防止TLE或者溢出。
比如說假如交易次數(shù)達到天數(shù)的一半,那么最大收益可以直接算出來,不用管交易次數(shù)的限制。
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
int n = prices.size();
if (n < 2)
return 0;
if (k > n / 2)
return quickSolver(prices);
int maxPro = 0;
vector<vector<int>> dp(k+1, vector<int>(n+1, 0));
for (int i=1; i<=k; i++) {
int tmpMax = dp[i-1][1] - prices[0];
for (int j=1; j<=n; j++) {
dp[i][j] = max(dp[i][j-1], tmpMax + prices[j-1]);
tmpMax = max(tmpMax, dp[i-1][j] - prices[j-1]);
maxPro = max(maxPro, dp[i][j]);
}
}
return maxPro;
}
int quickSolver(vector<int> prices)
{
int n = prices.size();
int res = 0;
for (int i=1; i<n; i++) {
if (prices[i] > prices[i-1])
res += prices[i] - prices[i-1];
}
return res;
}
};