递归

  • 状态: 怎么描述问题, 当前是持有/未持有状态下, 能获得的最大利润
  • 缩小问题规模: 到哪里去/从哪里来
  • 当前状态下,如何做选择才能获利最大? 到哪里去 ```typescript export function maxProfit(prices: number[]): number { // [day…最后一天]最大利润

    const cache: number[][] = new Array(prices.length) .fill(0) .map(() => new Array(2).fill(-1));

    function backtrack(day: number, state: boolean): number { / state=true表示持有状态 /

    // base case if (day >= prices.length) {

    1. return 0;

    }

    if (cache[day][state ? 0 : 1] !== -1) return cache[day][state ? 0 : 1];

    if (state) {

    1. cache[day][state ? 0 : 1] = Math.max(
    2. prices[day] + backtrack(day + 1, !state),
    3. backtrack(day + 1, state)
    4. );

    } else {

    1. cache[day][state ? 0 : 1] = Math.max(
    2. -prices[day] + backtrack(day + 1, !state),
    3. backtrack(day + 1, state)
    4. );

    }

    return cache[day][state ? 0 : 1]; }

    return backtrack(0, false); }

console.log(maxProfit([7, 1, 5, 3, 6, 4]));

  1. <a name="jNmCi"></a>
  2. # 动态规划
  3. - State: 第几天,持有或者非持有状态 的最优价值
  4. - 涉及到连续不连续的问题往往需要某个方法来体现。这题目理论上是不连续的问题,但是由于将price预先处理,因此这个不连续其实并不需要考虑,
  5. - 当前状态时如何形成的,以及它的最优解 从哪里来
  6. - 不连续处理
  7. ```typescript
  8. function maxProfit(prices: number[]): number {
  9. // State , status下 第几天的最优解
  10. const dp: number[][] = new Array(prices.length)
  11. .fill(0)
  12. .map(() => new Array(2).fill(-1));
  13. // base case
  14. dp[0][0] = 0;
  15. dp[0][1] = -prices[0];
  16. // make progress
  17. for (let i = 1; i < prices.length; i++) {
  18. // 未持有状态 该状态是前面保留的状态或是当天卖出
  19. // 当天卖出 卖出的是那一天的
  20. {
  21. const days = [...Array(i).keys()].filter(
  22. (day) => prices[day] < prices[i]
  23. );
  24. const profits = days.map((day) => dp[day][1] + prices[i]);
  25. dp[i][0] = Math.max(dp[i - 1][0], Math.max(...profits));
  26. }
  27. // 持有状态 该状态是前面保留的或是当天买入
  28. {
  29. dp[i][1] = Math.max(dp[i - 1][1], dp[i][0] - prices[i]);
  30. }
  31. }
  32. console.table(dp);
  33. return dp[prices.length - 1][0];
  34. }
  • 连续

    1. function maxProfit(prices: number[]): number {
    2. // State , status下 第几天的最优解
    3. const dp: number[][] = new Array(prices.length)
    4. .fill(0)
    5. .map(() => new Array(2).fill(-1));
    6. // base case
    7. dp[0][0] = 0;
    8. dp[0][1] = -prices[0];
    9. // make progress
    10. for (let i = 1; i < prices.length; i++) {
    11. // 未持有状态 该状态是前面保留的状态或是当天卖出
    12. // 当天卖出 卖出的是那一天的
    13. {
    14. dp[i][0] = Math.max(dp[i - 1][0], dp[i-1][1] + prices[i]);
    15. }
    16. // 持有状态 该状态是前面保留的或是当天买入
    17. {
    18. dp[i][1] = Math.max(dp[i - 1][1], dp[i][0] - prices[i]);
    19. }
    20. }
    21. return dp[prices.length - 1][0];
    22. }