买卖股票的最佳时机IV–LeetCode188
题目
给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你最多可以完成 k 笔交易。注意: 你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例:
输入: [3,2,6,5,0,3], k = 2
输出: 7
解释: 在第 2 天 (股票价格 = 2) 的时候买入,在第 3 天 (股票价格 = 6) 的时候卖出,
这笔交易所能获得利润 = 6-2 = 4 。
随后,在第 5 天 (股票价格 = 0) 的时候买入,在第 6 天 (股票价格 = 3) 的时候卖出,
这笔交易所能获得利润 = 3-0 = 3 。
思路
和股票问题3的差别在于这里的交易次数是作为参数给出的,但是思想还是一样的。自己写完之后,提交出现超出内存限制的问题,结果发现抛出异常时k是一个很大的数。需要注意的是:一次交易至少需要 2 天,一天买,一天卖。因此如果 k 很大,大到大于等于 len / 2,就相当于股票问题2,此时使用贪心算法来求解。
代码如下:
class Solution {
public int maxProfit(int k, int[] prices) {
// 边界条件
if (prices == null || prices.length == 0 || k <= 0) {
return 0;
}
int n = prices.length;
// k超过数组长度的一半,贪心法求解。
if (k >= (n>>1)) {
return greedy(prices, n);
}
int[] dp = new int[k+1];
int[] min = new int[k+1];
for (int i = 1; i <= k; i++) {
min[i] = prices[0];
}
for (int i = 1; i < n; i++) {
for (int j = 1; j <= k; j++) {
min[j] = Math.min(min[j], prices[i]-dp[j-1]);
dp[j] = Math.max(dp[j], prices[i]-min[j]);
}
}
return dp[k];
}
// 贪心法求解
private int greedy(int[] prices, int n) {
int res = 0;
for (int i = 1; i < n; i++) {
if (prices[i-1] < prices[i]) {
res += prices[i]-prices[i-1];
}
}
return res;
}
}