一天一大 leet(每日温度)难度:中等 DAY-11

20200610

img

题目(难度:简单):

根据每日 气温 列表,请重新生成一个列表,对应位置的输出是需要再等待多久温度才会升高超过该日的天数。如果之后都不会升高,请在该位置用 0 来代替。

示例

输入: [73, 74, 75, 71, 69, 72, 76, 73]
输出: [1, 1, 4, 2, 1, 1, 0, 0]

提示

气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。

抛砖引玉

img

先阐述下题目的意思:
7374757169727673
[74, 75, 71, 69, 72, 76, 73][75, 71, 69, 72, 76, 73][71, 69, 72, 76, 73][69, 72, 76, 73][ 72, 76, 73][76, 73][73][]
74>7375>7476>7572>7172>6976>72
原数组的索引: 73 ->0,74 -> 1原数组的索引: 74 ->1,75 -> 2原数组的索引: 75 ->2,76 -> 6原数组的索引: 71 ->3,72 -> 5原数组的索引: 69 ->4,72 -> 5原数组的索引: 72 ->4,72 -> 600
1-02-16-25-35-46-400

遍历数组
返回数组中 A 之后项第一个大于 A 的第一个数字的索引
填充索引到新数组中 A 对应的索引位置

/**
 * @param {number[]} T
 * @return {number[]}
 */
var dailyTemperatures = function (T) {
  var len = T.length
  var _result = Array(len).fill(0)
  for (var i = 0; i < len; i++) {
    var item = T[i]
    if (item < 100) {
      for (var j = i + 1; j < len; j++) {
        if (T[j] > item) {
          _result[i] = j - i
          break
        }
      }
    }
  }
  return _result
}

官方答案

暴力
  • 反向遍历温度列表。对于每个元素 T[i],在数组 next 中找到从 T[i] + 1 到 100 中每个温度第一次出现的下标,
    将其中的最小下标记为 warmerIndex,则 warmerIndex 为下一次温度比当天高的下标。
    如果 warmerIndex 不为无穷大,则 warmerIndex - i 即为下一次温度比当天高的等待天数,最后令 next[T[i]] = i。
  • 为什么上述做法可以保证正确呢?因为遍历温度列表的方向是反向,当遍历到元素 T[i] 时,
    只有 T[i] 后面的元素被访问过,即对于任意 t,当 next[t] 不为无穷大时,一定存在 j 使得 t 等于 T[j] 且 i < j。
    又由于遍历到温度列表中的每个元素时都会更新数组 next 中的对应温度的元素值,
    因此对于任意 t,当 next[t] 不为无穷大时,令 j = next[t],则 j 是满足 t 等于 T[j] 且 i < j 的最小下标
/**
 * @param {number[]} T
 * @return {number[]}
 */
var dailyTemperatures = function (T) {
  var length = T.length
  var ans = Array(length).fill(0)
  var next = Array(101).fill(Number.MAX_VALUE)
  for (var i = length - 1; i >= 0; --i) {
    var warmerIndex = Number.MAX_VALUE
    for (var t = T[i] + 1; t <= 100; ++t) {
      if (next[t] < warmerIndex) {
        warmerIndex = next[t]
      }
    }
    if (warmerIndex < Number.MAX_VALUE) {
      ans[i] = warmerIndex - i
    }
    next[T[i]] = i
  }
  return ans
}
单调栈
  • 栈空的情况下,当前元素入栈
  • 当前元素比栈顶大,则让小项出栈,栈顶更新,直到当前元素比栈顶小,停止出栈
  • 此时的栈顶元素就是当前项右边的第一个比自己大的元素,计算距离并让当前项入栈

img

/**
 * @param {number[]} T
 * @return {number[]}
 */
var dailyTemperatures = function (T) {
  const res = new Array(T.length).fill(0)
  const stack = []
  for (let i = T.length - 1; i >= 0; i--) {
    while (stack.length && T[i] >= T[stack[stack.length - 1]]) {
      stack.pop()
    }
    if (stack.length && T[i] < T[stack[stack.length - 1]]) {
      res[i] = stack[stack.length - 1] - i
    }
    stack.push(i)
  }
  return res
}

高手在民间

  • 遍历整个数组,如果栈不空,且当前数字大于栈顶元素,所以需要取出栈顶元素,
    由于当前数字大于栈顶元素的数字,而且一定是第一个大于栈顶元素的数,直接求出下标差就是二者的距离。

  • 继续看新的栈顶元素,直到当前数字小于等于栈顶元素停止,然后将数字入栈,
    这样就可以一直保持递减栈,且每个数字和第一个大于它的数的距离也可以算出来。

/**
 * @param {number[]} T
 * @return {number[]}
 */
var dailyTemperatures = function (T) {
  let res = new Array(T.length).fill(0)
  let stack = []
  for (let i = 0; i < T.length; i++) {
    while (stack.length && T[i] > T[stack[stack.length - 1]]) {
      let topIdx = stack.pop()
      res[topIdx] = i - topIdx
    }
    stack.push(i)
  }
  return res
}

博客: 小书童博客(http://gaowenju.com/)

公号: 坑人的小书童
坑人的小书童

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
探险家小扣的行动轨迹,都将保存在记录仪中。expeditions[i] 表示小扣第 i 次探险记录,用一个字符串数组表示。其中的每个「营地」由大小写字母组成,通过子串 -> 连接。例:"Leet->code->Campsite",表示到访了 "Leet"、"code"、"Campsite" 三个营地。expeditions[0] 包含了初始小扣已知的所有营地;对于之后的第 i 次探险(即 expeditions[i] 且 i > 0),如果记录中包含了之前均没出现的营地,则表示小扣 新发现 的营地。 请你找出小扣发现新营地最多且索引最小的那次探险,并返回对应的记录索引。如果所有探险记录都没有发现新的营地,返回 -1。注意: 大小写不同的营地视为不同的营地; 营地的名称长度均大于 0。用python实现。给你几个例子:示例 1: 输入:expeditions = ["leet->code","leet->code->Campsite->Leet","leet->code->leet->courier"] 输出:1 解释: 初始已知的所有营地为 "leet" 和 "code" 第 1 次,到访了 "leet"、"code"、"Campsite"、"Leet",新发现营地 2 处:"Campsite"、"Leet" 第 2 次,到访了 "leet"、"code"、"courier",新发现营地 1 处:"courier" 第 1 次探险发现的新营地数量最多,因此返回 1。示例 2: 输入:expeditions = ["Alice->Dex","","Dex"] 输出:-1 解释: 初始已知的所有营地为 "Alice" 和 "Dex" 第 1 次,未到访任何营地; 第 2 次,到访了 "Dex",未新发现营地; 因为两次探险均未发现新的营地,返回 -1
04-23
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值