题目来源:https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/
问题描述
188. Best Time to Buy and Sell Stock IV
Hard
Say you have an array for which the ithelement is the price of a given stock on day i.
Design an algorithm to find the maximum profit. You may complete at most ktransactions.
Note:
You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
Example 1:
Input: [2,4,1], k = 2
Output: 2
Explanation: Buy on day 1 (price = 2) and sell on day 2 (price = 4), profit = 4-2 = 2.
Example 2:
Input: [3,2,6,5,0,3], k = 2
Output: 7
Explanation: Buy on day 2 (price = 2) and sell on day 3 (price = 6), profit = 6-2 = 4.
Then buy on day 5 (price = 0) and sell on day 6 (price = 3), profit = 3-0 = 3.
------------------------------------------------------------
题意
给定一个价格序列prices和一个正整数k,k表示可以在这个价格序列上进行的交易次数的最大值(一次交易包括一次买入行为+一次卖出行为,可以在同一个时刻既买入又卖出)。求最大获利?
------------------------------------------------------------
思路
动态规划dp[i][j]表示截止到第j个月最多进行i次交易的最大获利(不一定要在第j个月有发生交易)。递推关系为:
dp[i][j] = max(dp[i-1][u] + prices[j] – prices[u]), u <= j
由于dp[i][]仅仅与dp[i-1][]有关,因此可以状态压缩将一个二维动态规划数组变成两个一维动态规划数组。
这样的算法时间复杂度是O(n^2*k)的。可以进一步优化时间复杂度为O(nk). 注意到在j从1向n-1遍历的过程中,dp[i-1][u] – prices[u]有平方级别的重复计算,因此考虑用变量localMax维护dp[i-1][u] – prices[u],在计算dp[i][j]的同时更新localMax. 递归式组为:
dp[i][j] = max(cur[i][j-1], localMax + prices[j])
localMax = max(localMax, dp[i-1][j] - prices[j])
还有一个与动态规划无关但是可以优化的点是当k>n/2时,实际上没有了交易次数的限制,因为最大的交易次数的限制就是n/2,因此可以直接用O(n)算法算出最大获利,无需使用动态规划
------------------------------------------------------------
代码
class Solution {
public int maxProfit(int k, int[] prices) {
int n = prices.length;
if (n == 0 || k == 0) {
return 0;
}
if (k > n/2) {
int ans = 0;
for (int i=1; i<n; ++i) {
ans += prices[i] > prices[i-1]? prices[i] - prices[i-1]: 0;
}
return ans;
}
int[] pre = new int[n], cur = new int[n];
int localMax = 0;
for (int i=0; i<k; ++i) {
localMax = pre[0] - prices[0];
for (int j=1; j<n; ++j) {
cur[j] = Math.max(cur[j-1], localMax + prices[j]);
localMax = Math.max(localMax, pre[j] - prices[j]);
}
pre = Arrays.copyOf(cur, n);
}
return cur[n-1];
}
}