问题出在著名的leetcode problem(或在其他类似情况下),最好以最多k笔交易买卖股票。 这是问题的屏幕截图:
我正在尝试理解这种DP解决方案。您可以忽略大k的第一部分。我不了解dp部分的工作原理。
class Solution(object):
def maxProfit(self, k, prices):
"""
:type k: int
:type prices: List[int]
:rtype: int
"""
# for large k greedy approach (ignore this part for large k)
if k >= len(prices) / 2:
profit = 0
for i in range(1, len(prices)):
profit += max(0, prices[i] - prices[i-1])
return profit
# Don't understand this part
dp = [[0]*2 for i in range(k+1)]
for i in reversed(range(len(prices))):
for j in range (1, k+1):
dp[j][True] = max(dp[j][True], -prices[i]+dp[j][False])
dp[j][False] = max(dp[j][False], prices[i]+dp[j-1][True])
return dp[k][True]
我能够驱动类似的解决方案,但是它使用两行(dp和dp2)而不是仅一行(以上解决方案中的dp)。对我来说,解决方案似乎是覆盖自身的值,对于这种解决方案来说,这看起来不合适。但是答案有效并通过了leetcode。
答案 0 :(得分:2)
让我们说几句话:
for i in reversed(range(len(prices))):
在考虑以后的价格之后,我们已经预先知道了每个未来价格。
for j in range (1, k+1):
对于将这个价格视为k
两次价格交易之一的每种可能性。
dp[j][True] = max(dp[j][True], -prices[i]+dp[j][False])
如果我们认为这可能是一次购买-由于我们在时间上会倒退,那么购买就意味着已完成交易-我们在考虑{{1 }}次购买(j
)或(2)减去此价格作为购买并添加我们已经获得的最佳结果,其中包括第dp[j][True]
次销售(j
)。>
-prices[i] + dp[j][False]
否则,我们可能会将其视为一笔交易(由于我们往后退,因此是交易的前半部分),因此我们选择(1)已考虑的第 dp[j][False] = max(dp[j][False], prices[i]+dp[j-1][True])
次交易中的最佳交易({{1 }}),或者(2)我们将此价格作为销售价格,并加上到目前为止,我们对第一批j
完成的交易(dp[j][False]
)的最佳结果。
请注意,第一个(j - 1)
是指第prices[i] + dp[j-1][True]
个“半交易”,如果您愿意的话,因为我们会倒退,所以这笔交易会在以更高的价格迭代。然后,我们可以考虑将这个价格作为第dp[j][False]
次销售来覆盖它。