代码随想录day50|739每日温度496下一个更大元素I|01笔记

102 阅读4分钟
  • 代码随想录 (programmercarl.com)
  • 第一印象

  • 暴力的解法就是两层遍历,寻找每天对应的下一个高温。
  • 讲解观后感

  • 单调栈:

  • 通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了。时间复杂度为O(n)。
  • 单调栈的本质是空间换时间,因为在遍历的过程中需要用一个栈来记录右边第一个比当前元素高的元素,优点是整个数组只需要遍历一次。
  • 本题我们需要使用单调递增的栈(从栈头到栈底)栈内直接记录下标。这样出现较大元素时就可以通过弹出和压入过程中的元素来产生结果值。我们从头开始遍历。 当当前元素小于或等于栈顶元素时,我们直接将元素下标放到栈顶。
    当当前元素大于栈顶元素时,我们就需要桉顺序弹出栈顶所有比当前元素小的下标,并计算结果。
  • 根据题目要求,我们要将结果集初始长度为temperature长度,并将数值全初始为0。
  • 解题代码

  • 单调栈展开讨论
  •     func dailyTemperatures(temperatures []int) []int {
            res := make([]int, len(temperatures))
            // 初始化栈顶元素为第一个下标索引0
            stack := []int{0}
        
            for i := 1; i < len(temperatures); i++ {
                top := stack[len(stack)-1]
                if temperatures[i] < temperatures[top] {
                    stack = append(stack, i)
                } else if temperatures[i] ==  temperatures[top] {
                    stack = append(stack, i)
                } else {
                    for len(stack) != 0 && temperatures[i] > temperatures[top] {
                        res[top] = i - top
                        stack = stack[:len(stack)-1]
                        if len(stack) != 0 {
                            top = stack[len(stack)-1]
                        }
                    }
                    stack = append(stack, i)
                }
            }
            return res
        }
    
  • 单调栈精简版
  •     // 单调递增栈(从栈头到栈底)
        func dailyTemperatures(num []int) []int {
            ans := make([]int, len(num))
            stack := []int{}
            for i, v := range num {
                // 栈不空,且当前遍历元素 v 破坏了栈的单调性
                for len(stack) != 0 && v > num[stack[len(stack)-1]] {
                    // pop
                    top := stack[len(stack)-1]
                    stack = stack[:len(stack)-1]
        
                    ans[top] = i - top
                }
                stack = append(stack, i)
            }
            return ans
        }
    
  • 496下一个更大元素I

  • 代码随想录 (programmercarl.com)
  • 第一印象

  • 这题和上题的区别就是变成了两个数组,因此我们需要再nums2中筛选出nums1中存在的元素。第一想法是首先用上题的方法得到长度为nums长度的结果集。然后通过nums对应的位置再筛选结果集得到最终答案。
  • 讲解观后感

  • 多次遍历的方法代码比较繁琐。我们可以直接在遍历nums2的过程中通过判断元素是否在nums1中来决定是否更新结果。
  • 因为题目说明不会出现重复的元素,且nums1是nums2的子集。那么我们可以直接使用map来记录nums中元素的出现情况。
  • 我们还是选用单调递增(从栈头到栈底)的栈。栈内直接记录元素在nums2中的下标。这样出现较大元素时就可以通过弹出和压入过程中的元素来产生结果值。我们从头开始遍历nums2
    当当前元素小于或等于栈顶元素时,我们直接将元素下标放到栈顶。
    当当前元素大于栈顶元素时,如果其在nums1中出现,我们就需要桉顺序弹出栈顶所有比当前元素小的下标,并计算结果。
  • 根据题目要求,我们要将结果集初始长度为nums1的长度,并将数值初始为-1。
  • 解题代码

  • 展开讨论版
  •     func nextGreaterElement(nums1 []int, nums2 []int) []int {
            res := make([]int, len(nums1))
            for i := range res { res[i] = -1 }
            m := make(map[int]int, len(nums1))
            for k, v := range nums1 { m[v] = k }
        
            stack := []int{0}
            for i := 1; i < len(nums2); i++ {
                top := stack[len(stack)-1]
                if nums2[i] < nums2[top] {
                    stack = append(stack, i)
                } else if nums2[i] == nums2[top] {
                    stack = append(stack, i)
                } else {
                    for len(stack) != 0 && nums2[i] > nums2[top] {
                        if v, ok := m[nums2[top]]; ok {
                            res[v] = nums2[i]
                        }
                        stack = stack[:len(stack)-1]
                        if len(stack) != 0 {
                            top = stack[len(stack)-1]
                        }
                    }
                    stack = append(stack, i)
                }
            }
            return res
        }
    
  • 精简版
  •     func nextGreaterElement(nums1 []int, nums2 []int) []int {
            res := make([]int, len(nums1))
            for i:= range res {
                res[i] = -1
            }
            mp := map[int]int{}
            for i,v := range nums1 {
                mp[v] = i
            }
            // 单调栈
            stack := []int{}
            stack = append(stack,0)
        
            for i:=1; i<len(nums2); i++ {
                for len(stack) >0 && nums2[i] > nums2[stack[len(stack)-1]] {
        
                    top := stack[len(stack)-1]
        
                    if _, ok := mp[nums2[top]]; ok {    // 看map里是否存在这个元素
                        index := mp[nums2[top]];        // 根据map找到nums2[top] 在 nums1中的下标
                        res[index] = nums2[i]
                    }
        
                    stack = stack[:len(stack)-1]        // 出栈
                }
                stack = append(stack, i)
            } 
            return res
        }