前端算法面试必刷题系列[51]

302 阅读3分钟

这个系列没啥花头,就是纯 leetcode 题目拆解分析,不求用骚气的一行或者小众取巧解法,而是用清晰的代码和足够简单的思路帮你理清题意。让你在面试中再也不怕算法笔试。

96. 买卖股票的最佳时机 (best-time-to-buy-and-sell-stock)

标签

  • 数组
  • 简单

题目

leetcode 传送门

这里不贴题了,leetcode打开就行,题目大意:

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

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

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

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

基本思路

简单题,数组遍历判断

  1. 设置最大利润变量和当前最小价格点
  2. 遍历数组,如果当前值小于最小值,更新最小值,否则最小值不变,看利润,当当前利润大于历史最大,更新最大利润值
  3. 返回最大利润

写法实现

var maxProfit = function(prices) {
  let [min_point, max_profit] = [Infinity, 0];
  prices.map(curItem => {
    // 如果当前值小于最小值
    if (curItem < min_point) {
      // 更新最小值
      min_point = curItem
      // 否则最小值不变,看利润,当当前利润大于历史最大,更新
    } else if (curItem - min_point > max_profit) {
      max_profit = curItem - min_point
    }
  })
  return max_profit
};

97. 买卖股票的最佳时机 II (best-time-to-buy-and-sell-stock-ii)

标签

  • 数组
  • 转化思维
  • 简单

题目

leetcode 传送门

这里不贴题了,leetcode打开就行,题目大意:

给定一个数组 prices ,其中 prices[i] 是一支给定股票第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

输入: prices = [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
     随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3

基本思想

这题看似情况变多,实际上更简单,每次涨了就买就行(不涨不买),最大总和就是每次涨了的钱的总和

写法实现

var maxProfit = function(prices) {
  let max_profit = 0;
  for (let i = 0; i < prices.length; i++) {
    // 明天大于今天,就加上上涨的钱
    if (prices[i] < prices[i+1]) {
      max_profit += prices[i+1] - prices[i]
    }
  } 
  return max_profit
};

let prices = [7,1,5,3,6,4]
console.log(maxProfit(prices))

98. 买卖股票的最佳时机 III (best-time-to-buy-and-sell-stock-iii)

标签

  • 转化思路
  • 困难

题目

leetcode 传送门

这里不贴题了,leetcode打开就行,题目大意:

给定一个数组,它的第 i 个元素是一支给定的股票在第 i 天的价格。

设计一个算法来计算你所能获取的最大利润。你最多可以完成 两笔 交易。

注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。

输入:prices = [3,3,5,0,0,3,1,4]
输出:6
解释:在第 4 天(股票价格 = 0)的时候买入,在第 6 天(股票价格 = 3)的时候卖出,
这笔交易所能获得利润 = 3-0 = 3 。
     随后,在第 7 天(股票价格 = 1)的时候买入,
     在第 8 天 (股票价格 = 4)的时候卖出,这笔交易所能获得利润 = 4-1 = 3
输入:prices = [1,2,3,4,5]
输出:4
解释:在第 1 天(股票价格 = 1)的时候买入,在第 5 天 (股票价格 = 5)的时候卖出, 
这笔交易所能获得利润 = 5-1 = 4 。   
     注意你不能在第 1 天和第 2 天接连购买股票,之后再将它们卖出。   
     因为这样属于同时参与了多笔交易,你必须在再次购买前出售掉之前的股票。

基本思想

由于我们最多可以完成两笔交易,因此在任意一天结束之后,我们会处于以下五个状态中的一种:

  1. 未进行过任何操作
  2. 只进行了第一次买操作
  3. 进行了一次买操作和一次卖操作,即完成了一笔交易;
  4. 在完成了一笔交易的前提下,进行了第二次买操作;
  5. 完成了全部两笔交易。

我们的目标是最大化收益,第一种收益为 0,不考虑,对于剩下的四个状态,我们分别将它们当前的最大利润记为 buy1, sell1, buy2, sell2

那我们下面状态转移其实就是描述,上一个最大收益与下一个最大收益状态之间的关系。 为什么需要 Math.max 每天都会产生新的可能最大情况,前面的是(历史最大,后面的是可能最大)

写法实现

var maxProfit = function(prices) {
  // 其实这里就是 4种情况点的转换
  let [buy1, sell1, buy2, sell2] = [- Infinity, 0, - Infinity, 0]
  for (let i = 0; i < prices.length; i++) {
    // 第一次买入,就是减今天价格,最大值就是今天的最大利润,跟前面轮数的最大利润相比取最大
    buy1 = Math.max(buy1, - prices[i])
    // 第一次买入后,根据题意,按顺序先卖出
    sell1 = Math.max(sell1, buy1 + prices[i])
    // 再买第二次,用上一个最大利润减去今天要买的
    buy2 = Math.max(buy2, sell1 - prices[i])
    sell2 = Math.max(sell2, buy2 + prices[i])
  }
  return sell2
};

let prices = [3,3,5,0,0,3,1,4]
console.log(maxProfit(prices))

另外向大家着重推荐下这位大哥的文章,非常深入浅出,对前端进阶的同学非常有作用,墙裂推荐!!!核心概念和算法拆解系列

今天就到这儿,想跟我一起刷题的小伙伴可以加我微信哦 搜索我的微信号infinity_9368,可以聊天说地 加我暗号 "天王盖地虎" 下一句的英文,验证消息请发给我 presious tower shock the rever monster,我看到就通过,暗号对不上不加哈,加了之后我会尽我所能帮你,但是注意提问方式,建议先看这篇文章:提问的智慧

参考