LeetCode 188. Best Time to Buy and Sell Stock IV
题目:
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[k][num] = argmaxi dp[k-1][i]+ones[i][num]。(dp[i][j]代表在j日前i项交易的最大值,ones[i][j]代表i~j日一次交易的最大值)事实上这么做复杂度是非常高的,果不其然,超时,下面是超时的代码:
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
if (prices.size() <= 1)return 0;
else if (k == 0)return 0;
else if (k + 1 >= prices.size())
{
int sum = 0;
for (int index = 0; index < prices.size() - 1; index++)
{
sum += maxProfit_one(prices, index, index + 1);
}
return sum;
}
vector<vector<int>> dp(k, vector<int>(prices.size(),0));
vector<vector<int>> ones(prices.size(), vector<int>(prices.size(), 0));
for (int k_index = 1; k_index <= prices.size() - k; k_index++)
for (int index = 0; index < prices.size() - k_index; index++)
{
ones[index][index + k_index] = maxProfit_one(prices, index, index + k_index);
}
for (int index = 1; index < prices.size(); index++)
{
dp[0][index] = ones[0][index];
}
for (int num_k = 1; num_k < k; num_k++)
for (int index = 2; index < prices.size(); index++)
{
dp[num_k][index] = max(dp[num_k - 1][index - 1] + ones[index - 1][index],dp[]);
//cout << num_k << "," << index << ":" << max_value<<endl;
}
return dp[k - 1][prices.size()-1];
}
//[left,right]
int maxProfit_one(vector<int>& prices, int left, int right)
{
int now_num = prices[left];
int min_num = now_num;
int max_money = 0;
int money = 0;
for (int index = left; index <= right; index++)
{
if (prices[index] > now_num)
{
money += (prices[index] - now_num);
now_num = prices[index];
}
else if (min_num > prices[index])
{
max_money = max(max_money, money);
money = 0;
min_num = prices[index];
now_num = min_num;
}
else continue;
}
max_money = max(max_money, money);
return max_money;
}
};
之后我又测试了各种方法,要不出错,要不超时…最后AC的思路如下:
用二维数组dp[i][j]存储第0~j日最多i次操作所得到的最大利润。
用二维数组dps[i][j]存储第0~j日最多i次操作(第2*j次操作为卖出prices[i])所得到的最大利润。
用一维数组ones[i]存储 prices[i+1] > prices[i] ? prices[i+1] - prices[i] : 0
dps[i][j] = max(dps[i][j - 1] + prices[j] - prices[j - 1], dp[i - 1][j - 1] + ones[j - 1]);
dp[i][j] = max(dps[i][j],dp[num_k][i]);
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
if (prices.size() <= 1)return 0;
else if (k == 0)return 0;
else if (k + 1 >= prices.size())
{
int sum = 0;
for (int index = 0; index < prices.size() - 1; index++)
{
if (prices[index] < prices[index + 1])
sum += prices[index + 1] - prices[index];
}
return sum;
}
vector<vector<int>> dp(k+1, vector<int>(prices.size(),0));
vector<vector<int>> dps(k+1, vector<int>(prices.size(), 0));
vector<int> ones(prices.size() - 1, 0);
for (int index = 0; index < prices.size() - 1; index++)
{
if (prices[index] < prices[index + 1])
ones[index] = prices[index + 1] - prices[index];
}
for (int index = 1; index <= k; index++)
{
dp[index][1] = ones[0];
dps[index][1] = dp[index][1];
}
for (int num_k = 1; num_k <= k; num_k++)
for (int index = 2; index < prices.size(); index++)
{
dps[num_k][index] = max(dps[num_k][index - 1] + prices[index] - prices[index - 1], dp[num_k - 1][index - 1] + ones[index - 1]);
dp[num_k][index] = max(dps[num_k][index],dp[num_k][index - 1]);
}
return dp[k][prices.size()-1];
}
};