leetcode每天一题:【买卖股票的最佳时机】(简单)

110 阅读2分钟

这是我参与2022首次更文挑战的第36天,活动详情查看:2022首次更文挑战

题目描述

leetcode题目地址

提供一个数组prices,然后索引代表的是第几天,对应的值代表的是股票当天的价格。

然后你需要选择在第几天买入股票,然后在第几天卖出股票。

返回所赚到的最大的收益。

如果不能赚到收益,则返回0

注意:卖出时间要比买入时间晚。 你不能在没买入的时候就卖出。不符合常理。

举个例子:

prices: [5,4,1,2,3]
返回: 23-1,不是5-1,因为要先买入,再卖出)

prices: [5,4,3,2,1]
返回: 0 (因为都是递减的,没有最大收益)

prices的长度大于等于1,小于等于100000。 每一项的值大于等于0,小于等于10000。

思路分析

第一种方法(错误)

这道题按照常规方法来想,就是定义一个变量res,记录最大的收益。

然后对数组进行嵌套遍历, 第一层从0开始遍历,第二层从第一层的索引开始遍历

然后两个索引对应的值相减,如果结果大于0,并且大于res,则覆盖res。

否则继续遍历。

等到遍历结束的时候,得到的res就是最大的收益。

代码如下:

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function (prices) {
  let res = 0
  for (let i = 0; i < prices.length - 1; i++) {
    for (let j = i + 1; j < prices.length; j++) {
      const profit = prices[j] - prices[i]
      if (profit > 0 && profit > res) {
        res = profit
      }
    }
  }
  return res
};

但是我们忽略了题目的补充条件,prices的长度是有可能达到100000的,所以这样嵌套遍历,耗时太长。

导致超出时间限制。

image.png

那能不能一次遍历就能实现的呢?

可以

第二种方法(正确)

我们定义2个变量,res代表最大的收益,默认是0max为当前遍历到的最大元素, 默认是最后一个元素。

我们从后往前遍历

如果当前遍历的元素比max大,则把它赋值给max,替换max

如果当前遍历的元素比max小,则把max和它相减,结果与res比较,如果比res大则替换res

这样子遍历结束后,可以找到最大的那个元素,和最大的收益。如果没有找到,则res是0

返回res即可。

代码如下:

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function (prices) {
  const len = prices.length
  let res = 0
  let max = prices[len - 1]
  for (let i = len - 1; i >= 0; i--) {
    if (prices[i] > max) {
      max = prices[i]
    } else {
      res = Math.max(res, max - prices[i])
    }
  }
  return res
};

image.png