题意:

image.png

解题思路:

  1. 思路:
  2. 状态: dp[i][k][0]表示第i天进行了k次交易,目前不持有股票;dp[i][k][1]表示第i天进行了k次交易,目前持有股票.
  3. 状态转移方程:
  4. 1、当天进行了k次交易,并不持有股票的最大收益为两种情况取大者:一、前一天交易了k次本身也不持有股票;二、前一天进行了k次交易,并持有股票,今天卖了。交易发生在当天,所以前一天的交易次数是k, 不是k - 1
  5. dp[i][k][0] = max(dp[i - 1][k][0], dp[i - 1][k][1] + prices[i]);
  6. 2、当天进行了k次交易,并持有股票的最大收益为两种情况取大者:一、前一天交易了k次本身持有股票;二、前一天进行了最多k - 1次交易,并不持有股票,当天买入了。当天还能买入,说明之前交易次数没有达到k次。
  7. dp[i][k][1] = max(dp[i - 1][k][1], dp[i - 1][k - 1][0] - prices[i]);

PHP代码实现:

  1. class Solution {
  2. /**
  3. * @param Integer[] $prices
  4. * @return Integer
  5. */
  6. function maxProfit($prices) {
  7. return $this->maxProfitO1($prices);
  8. if (empty($prices)) return 0;
  9. $dp = [];
  10. $maxK = 2;
  11. for ($i = 0; $i < count($prices); $i++) {
  12. for ($k = $maxK; $k >= 1; $k--) {
  13. if ($i == 0) {
  14. $dp[$i][$k][0] = 0;
  15. $dp[$i][$k][1] = -$prices[$i];
  16. continue;
  17. }
  18. $dp[$i][$k][0] = max($dp[$i - 1][$k][0], $dp[$i - 1][$k][1] + $prices[$i]);
  19. $dp[$i][$k][1] = max($dp[$i - 1][$k][1], $dp[$i - 1][$k - 1][0] - $prices[$i]);
  20. }
  21. }
  22. return $dp[count($prices) - 1][$maxK][0];
  23. }
  24. function maxProfitO1($prices) {
  25. if (empty($prices)) return 0;
  26. /**
  27. * $dp[$i][2][0] = max($dp[$i - 1][2][0], $dp[$i - 1][2][1] + $prices[$i]);
  28. * $dp[$i][2][1] = max($dp[$i - 1][2][1], $dp[$i - 1][1][0] - $prices[$i]);
  29. *
  30. * $dp[$i][1][0] = max($dp[$i - 1][1][0], $dp[$i - 1][1][1] + $prices[$i]);
  31. * $dp[$i][1][1] = max($dp[$i - 1][1][1], $dp[$i - 1][0][0] - $prices[$i]);
  32. */
  33. //对照上面做等价变形
  34. $dp_i00 = 0;
  35. $dp_i10 = 0;
  36. $dp_i20 = 0;
  37. $dp_i21 = PHP_INT_MIN;
  38. $dp_i11 = PHP_INT_MIN;
  39. for ($i = 0; $i < count($prices); $i++) {
  40. $dp_i20 = max($dp_i20, $dp_i21+ $prices[$i]);
  41. $dp_i21 = max($dp_i21, $dp_i10- $prices[$i]);
  42. $dp_i10 = max($dp_i10, $dp_i11+ $prices[$i]);
  43. $dp_i11 = max($dp_i11, $dp_i00-$prices[$i]);
  44. }
  45. return $dp_i20;
  46. }
  47. }

GO代码实现:

  1. func maxProfit(prices []int) int {
  2. dp_i00, dp_i10, dp_i20 := 0, 0, 0
  3. dp_i11, dp_i21 := math.MinInt64, math.MinInt64
  4. for _, v := range prices {
  5. dp_i20 = max(dp_i20, dp_i21 + v)
  6. dp_i21 = max(dp_i21, dp_i10 - v)
  7. dp_i10 = max(dp_i10, dp_i11 + v)
  8. dp_i11 = max(dp_i11, dp_i00 - v)
  9. }
  10. return dp_i20
  11. }
  12. func max(a, b int) int {
  13. if a < b {
  14. return b
  15. }
  16. return a
  17. }