买卖股票的最佳时机 II

471 阅读2分钟

题目描述

给定一个数组 prices ,其中 prices[i] 是一支给定股票第 i 天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

方法一 贪心

解题思路

当天股票价格比前一天高即可进行一次盈利操作,多次盈利操作累加起来就可得出最大利润

代码示例

const maxProfit = function(prices) {
    let result = 0;
    let n = prices.length;
    for (let i = 1; i < n; ++i) {
        result += Math.max(0, prices[i] - prices[i - 1]);
    }
    return result;
};

复杂度分析

时间复杂度:O(n),其中n为数组的长度。我们只需要遍历一次数组即可
空间复杂度:O(1)。只需要常数空间存放若干变量。

方法二 动态规划

解题思路

每天交易结束后只可能存在手里有一支股票或者没有股票的状态

  1. dp[i][0] 表示第i天手中没有股票的最大利润,没有股票可能是前一天时就没有股票,或者前一天有股票,第i天卖出,公式如下:
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i])
  1. dp[i][1] 表示第i天手中持有股票的最大利润,持有股票可能是前一天时就持有股票,或者前一天没有股票,第i天买入,公式如下
dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);

代码实现

const maxProfit = function (prices) {
  const len = prices.length;
  const dp = new Array(len).fill(0).map(v => new Array(2).fill(0));
  dp[0][0] = 0;
  dp[0][1] = -prices[0];
  for (let i = 1; i < len; i++) {
    dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
    dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
  }
  return dp[len - 1][0];
};

复杂度分析

时间复杂度:O(n),其中 n 为数组的长度。一共有 2n 个状态,每次状态转移的时间复杂度为 O(1),因此时间复杂度为 O(2n)=O(n)
空间复杂度:O(n)。我们需要开辟 O(n) 空间存储动态规划中的所有状态。如果使用空间优化,空间复杂度可以优化至 O(1)

优化空间复杂度

只需要关注今天的状态和前一天的状态即可

const len = prices.length;
  let cash = 0;
  let hold = -prices[0];
  // 前一天持有现金的最大利润
  let preCash = cash;
  // 前一天持有股票的最大利润
  let preHold = hold;
  for (let i = 1; i < len; i++) {
    // 第i天持有现金的最大利润
    cash = Math.max(preCash, preHold + prices[i]);
    // 第i天持有股票的最大利润
    hold = Math.max(preHold, preCash - prices[i]);
    // 更新前一天持有现金的最大利润
    preCash = cash;
    // 更新前一天持有股票的最大利润
    preHold = hold;
  }
  return cash;

空间复杂度:O(1)。我们只需要常量个变量。