算法练习day50

45 阅读2分钟

一、每日温度

通常是一维数组,要寻找任意一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要用到单调栈了,时间复杂度为On

单调栈

单调栈的本质是空间换时间,用一个栈来记录我们遍历过的元素

  1. 单调栈里存放的元素是什么呢?存放下标
  2. 单调栈里的元素是递增还是递减呢,首先,为从栈头到栈底的顺序
    1. 如果要找元素右边第一个更大的元素,单调栈是递增的,如果当前元素是比栈头更大的元素,则栈头出栈,直到栈头大于当前元素,把当前元素入栈,保证单调站的递增
      1. 当前元素T[i] < T[st.top()]
      2. 当前元素T[i] = T[st.top()]
      3. 当前元素T[i] > T[st.top()]
    2. 如果要找元素右边第一个更小的元素,单调站是递减的,如果当前元素是比栈头更小的元素,则栈头出栈,直到栈头小于当前元素,把当前元素入栈,保证单调站的递减
/**
 * @param {number[]} temperatures
 * @return {number[]}
 */
var dailyTemperatures = function(temperatures) {
    let stack = [0]
    let result = new Array(temperatures.length).fill(0)
    for(let i = 1; i < temperatures.length;i++) {
        if(temperatures[i] <= temperatures[stack[0]]) {
            stack.unshift(i)
        } else {
            while(stack.length && temperatures[i] > temperatures[stack[0]]) {
                let j = stack.shift()
                result[j] = i - j
            }
            stack.unshift(i)
        }
    }
    return result
};

二、下一个更大元素1

nums1是nums2的子集,从nums1中元素在nums2中出现后第一个更大的元素,需要一个map来映射nums1的索引位置,记录最终结果,其他和上一题完全一样

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number[]}
 */
var nextGreaterElement = function(nums1, nums2) {
    let result = new Array(nums1.length).fill(-1)
    let stack = [0]
    let map = new Map()
    for(let i = 0; i < nums1.length;i++) {
        map.set(nums1[i], i)
    }
    for(let i = 1; i < nums2.length;i++) {
        while(stack.length && nums2[i] > nums2[stack[0]]) {
            let index = stack.shift()
            if(map.has(nums2[index])) {
                result[map.get(nums2[index])] = nums2[i]
            }
        }
        stack.unshift(i)
    }
    return result
};