leetcode-188-Best Time to Buy and Sell Stock IV
问题
Say you have an array for which the i-th 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).
Example 1:
1 | Input: [2,4,1], k = 2 |
Example 2:
1 | Input: [3,2,6,5,0,3], k = 2 |
分析
使用动态规划 $dp[i][j]$ 表示在 $prices[0…j]$ 中进行最多 $i$ 次交易所能获得的最大的利润。
根据在 $prices[j]$ 上的操作,$dp[i][j]$ 的求解可以分为两种情况。
- 在 $prices[j]$ 没有出售股票,则 $dp[i][j] = dp[i][j-1]$
- 在 $prices[j]$ 出售了股票,假设出售的股票是在 $k (0 \leq k < j)$ 点买入的则 $dp[i][j] = prices[j] - prices[k] + dp[i-1][k-1]$ 。
初始条件:$dp[i][j]$ 的第一维为 0 时,就是说没有进行过交易,那么所能够获得的最大利润自然是 0。$dp[i][j]$ 的第二维为 0 时,那么就是只考虑了 $prices[0]$ ,不可能产生交易,那么所能够获得的最大利润自然也是 0。由上面的分析可以看出,交易 $i$ 次的情况依赖于交易 $i-1$ 次的情况,那么我们可以以最大交易次数来作为DP的阶段。
目标:$dp[k][n-1]$。
不经过优化的代码如代码1所示,时间复杂度为$O(kn^2)$。
经过分析可以看出,最内层循环其实可以降维 $O(1)$ ,令 $maxTmp = dp[i-1][k-1] + prices[k]$ ,而且,$0 \leq k < j$ ,可以在每次迭代 $j$ 的时候(每次迭代结束时)对 $maxTmp$ 进行更新,并初始化 $maxTmp = prices[0]$。
经过优化之后的代码如代码2,时间复杂度 $O(kn)$.
另外,测试集中有k和n相当大的情况。根据贪心算法如果 有 $k >= n/2$ ,就能等同于可以在 $prices$ 进行无限制的买卖了。因此可以先对 k 和 n 之间的大小关系进行判断(否则无法AC)。
代码1
1 | class Solution { |
代码2
1 | class Solution { |
Author: Hatton.Liu
Link: http://hattonl.github.io/2020/03/20/leetcode-188/
License: 知识共享署名-非商业性使用 4.0 国际许可协议