再谈买卖股票的最佳时机|刷题打卡

337 阅读5分钟

可能此题之后就彻底放弃刷题了,一时兴起,也一时平淡。习惯最终无法养成,没有学到能够适合自己的路,很难走出一条具有特色的路,接下来的将花时间想明白自己能学会什么、产出什么、坚持什么。这次,无疑是失败的,来看看Copy攻城狮的最后一道题--买卖股票的最佳时机

题目描述

分类困难度👍👎
算法简单 (56.09%)1504-
标签 数组动态规划
公司 amazon | bloomberg | facebook | microsoft | uber

给定一个数组 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。

提示:

  • 1 <= prices.length <= 105
  • 0 <= prices[i] <= 104

思路分析

感觉有两个关键的点:

  • 一是找出最大利润,也就是数组中两个差值最大的值
  • 二是需要判断卖出价格要比买入价格大,也就是后一个值要比前一个值大。

Copy攻城狮的老套路--暴力解法走起!

AC 代码

暴力解法

/*
 * @lc app=leetcode.cn id=121 lang=javascript
 *
 * [121] 买卖股票的最佳时机
 */

// @lc code=start
/**
 * @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;
};
// @lc code=end

测试似乎没问题,满怀信心提交时就傻眼了,爆了!爆了!爆了!

Time Limit Exceeded
205/210 cases passed (N/A)
Testcase
[681,331,387,940,850,305,433,389,137,57,294,301,491,64,251,498,487,680,621,578,646,591,715,907,923,705,123,467,578,455,335,607,773,521,966,86,344,664,515,362,709,920,595,43,364,498,117,353,517,824,750,857,112,350,466,399,181,699,385,474,361,678,82,50,424,971,286,170,700,889,940,392,713,542,603,351,899,726,562,668,637,259,944,497,445,435,777,263,846,662,947,995,798,384,300,378,728,251,99,70,756,612,979,195,382,825,18,139,218,820,404,513,182,238,646,597,498,119,257,200,894,562,982,403,803,663,370,120,87,818,103,568,965,516,32,103,857,504,638,576,855,659,324,463,833,688,461,690,403,672,439,250,669,840,751,282,411,163,603,807,556,202,297,94,895,392,640,548,494,861,365,156,912,657,246,949,380,811,386,172,157,83,143,695,845,453,594,96,395,255,31,558,143,719,3,634,633,663,491,106,384,778,727,385,143,231,212,229,284,40,188,879,111,26,401,513,435,278,546,38,866,600,957,411,268,52,935,212,563,524,844,248,206,913,684,226,208,983,292,855,141,266,61,896,604,208,498,372,364,534,231,300,669,690,336,854,344,200,223,829,506,122,898,424,235,672,627,256,834,60,354,263,602,668,66,356,91………………]
Expected Answer
999

当数组长度太大的时候,应该是内存爆了,类似于Chrome卡死。

怎么办?看看社区的解法,试试大佬们常说的动态规划吧!

不明觉厉的动态规划

来自 一行代码 巧用reduce实现动态规划

JavaScript 中数组的 reduce 天然具备解动态规划方程的特性,本文暂且不做深入研究。

/*
 * @lc app=leetcode.cn id=121 lang=javascript
 *
 * [121] 买卖股票的最佳时机
 */

// @lc code=start
/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function (prices) {
  return prices.reduce(
    (p, v) => [Math.min(p[0], v), Math.max(p[1], v - p[0])],
    [Number.MAX_SAFE_INTEGER, 0]
  )[1];
};
// @lc code=end

// 210/210 cases passed (188 ms)
// Your runtime beats 15.3 % of javascript submissions
// Your memory usage beats 5.02 % of javascript submissions (54.8 MB)

总结

又是一个值得深入的概念,也不知道有什么好的方法能够尽快掌握这些解题的概念和思路,迷茫中……

本文正在参与「掘金 2021 春招闯关活动」, 点击查看活动详情