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

20200610

一天一大 leet(每日温度)难度:中等 DAY-11_第1张图片

题目(难度:简单):

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

示例

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

提示

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

抛砖引玉

一天一大 leet(每日温度)难度:中等 DAY-11_第2张图片

先阐述下题目的意思:

73 74 75 71 69 72 76 73
[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>73 75>74 76>75 72>71 72>69 76>72
原数组的索引: 73 ->0,74 -> 1 原数组的索引: 74 ->1,75 -> 2 原数组的索引: 75 ->2,76 -> 6 原数组的索引: 71 ->3,72 -> 5 原数组的索引: 69 ->4,72 -> 5 原数组的索引: 72 ->4,72 -> 6 0 0
1-0 2-1 6-2 5-3 5-4 6-4 0 0

遍历数组
返回数组中 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
}

单调栈

  • 栈空的情况下,当前元素入栈
  • 当前元素比栈顶大,则让小项出栈,栈顶更新,直到当前元素比栈顶小,停止出栈
  • 此时的栈顶元素就是当前项右边的第一个比自己大的元素,计算距离并让当前项入栈

一天一大 leet(每日温度)难度:中等 DAY-11_第3张图片

/**
 * @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/)

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

你可能感兴趣的:(一天一大leet)