LeetCode 121:买卖股票的时机

1,373 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情.

 买卖股票的最佳时机

题目描述

给定一个数组 prices ,它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。

你只能选择 某一天 买入这只股票,并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。

返回你可以从这笔交易中获取的最大利润。如果你不能获取任何利润,返回 0 。

示例 1: 

输入:[7,1,5,3,6,4]
输出:5
解释:在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
     注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。

示例2:

输入: prices = [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0。

解题思路 

我们需要找出给定数组中两个数字之间的最大差值(即,最大利润)。此外,第二个数字(卖出价格)必须大于第一个数字(买入价格)

思路一: 暴力法

但是暴力法提示超出时间限制
以下代码:

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function(prices) {
    // 暴力法提示 超出时间限制
    // let maxprofit = 0 ;
    // for (let i = 0 ; i < prices.length - 1; i++) {
    //     for (let j = i + 1 ; j < prices.length; j++) {
    //         let profit = prices[j] - prices[i];
    //         if (profit > maxprofit) {
    //             maxprofit = profit;
    //         }
    //     }
    // }
    // return maxprofit;
};

仅做思路而已。

思路二: 动态规划思想

第i天的最大收益只需要知道前i天的最低点就可以算出来了。而第i天以前(包括第i天)的最低点和i-1天的最低点有关,至此我们的动态方程就出来了。

dp[i] = min(d[i-1],prices[i]) 其中dp[0]=prices[0], 然后动态计算之后的就可以了。 得到了前i天的最低点以后,只需要维护一个maxprofit用来保存最大收益就可以了。 这个时候是空间复杂度O(n)的动态规划,实现代码如下:

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function(prices) {
    let maxprofit = 0, dp = [] ;
    // dp[i]表示截止到i,价格的最低点是多少
    dp[0] = prices[0];
    for (let i = 0 ; i < prices.length ; i++) {
        dp[i] = (dp[i - 1] < prices[i]) ? dp[i - 1] : prices[i];
        maxprofit = (prices[i] - dp[i]) > maxprofit ? prices[i] - dp[i] : maxprofit;
    }
    return maxprofit;
};

观察以上动态规划的辅助数组,其每一次只用到了dp[i]这一个空间,因此可以把数组改成单个变量来存储截止到第i天的价格最低点

思路三:双指针

用一个变量记录一个历史最低价格 minPrice,我们就可以假设自己的股票是在那天买的。那么我们在第 i 天卖出股票能得到的利润就是 prices[i] - minprice

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function (prices) {
  var minPrice = prices[0], maxProfit = 0;
  for (var i = 0; i < prices.length; i++) {
    if (prices[i] < minPrice) {
      minPrice = prices[i]
    } else if (prices[i] - minPrice > maxProfit) {
      maxProfit = prices[i] - minPrice
    }
  }
  return maxProfit;
};

时间复杂度: O(n)

空间复杂度: O(1)

参考资料

链接:

LeetCode 121.买卖股票的最佳时机 - 力扣(LeetCode)