方法1:动态规划法
https://mp.weixin.qq.com/s/voti73ay-Ko3mt0qwIDouQ
核心思路是找出第一次卖在哪天是最佳的
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
return f(k, prices);
}
int f(int k, vector<int>& prices) {
if (prices.size() <= 1) return 0;
vector<vector<int>> memo(prices.size(), vector<int>(k+1, -1));
return dp(prices, memo, 0, k);
}
int dp(vector<int>& prices, vector<vector<int>> memo, int start, int k)
{
if (start >= prices.size()) return 0;
if (k == 0) return 0;
if (memo[start][k] != -1) return memo[start][k];
int res = 0;
int cur_min = prices[start];
//这里求得是第一次sell在哪天是最佳的
for (int sell = start+1; sell < prices.size(); ++sell)
{
cur_min = min(cur_min, prices[sell]);
res = max(res, prices[sell]-cur_min+dp(prices, memo, sell+1, k-1));
}
memo[start][k] = res;
return res;
}
};
方法2:状态机
https://mp.weixin.qq.com/s/_xxnQP7hDIBSTpPsok8QIg
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
return maxProfit_k_any(k, prices);
}
int maxProfit_k_inf(vector<int>& prices) {
int dp_i_0 = 0;
int dp_i_1 = INT_MIN;
for (int i = 0; i < prices.size(); ++i)
{
int temp = dp_i_0;
dp_i_0 = max(dp_i_0, dp_i_1+prices[i]);
dp_i_1 = max(dp_i_1, temp-prices[i]);
}
return dp_i_0;
}
int maxProfit_k_any(int k, vector<int>& prices)
{
int n = prices.size();
if (n<=1) return 0;
if (k == 0) return 0;
if (k > n/2)
return maxProfit_k_inf(prices);
int max_k = k;
int dp[n][max_k+1][2] = {};
for (int i = 0; i < n; ++i)
{
dp[i][0][0] = 0;
dp[i][0][1] = INT_MIN;
}
for (int i = 0; i < n; ++i)
{
for (int k = 1; k <= max_k; ++k)
{
if (i==0) // base case
{
dp[0][k][0] = 0;
dp[0][k][1] = -prices[i];
}
else
{
dp[i][k][0] = max(dp[i-1][k][0], dp[i-1][k][1]+prices[i]);
dp[i][k][1] = max(dp[i-1][k][1], dp[i-1][k-1][0]-prices[i]);
}
}
}
return dp[n-1][max_k][0];
}
};