496. 下一个更大元素 I

发布时间 2023-03-22 21:14:30作者: zhangk1988

题目描述

nums2中元素都不同,num1是nums2的一个子集。
需要找出nums2中每个元素下一个更大的元素,在映射回nums1中?

f1-哈希表+左到右的单调栈

基本分析

  1. 向右找最近的更大的值,维护递增栈还是递减的栈,是严格的吗?需要维护非严格递减的栈,例如43342,33都会入栈。
  2. 找到的逻辑是什么?当遇到一个d > st[-1].值 时候,对st[-1]来说d就是他的最近的更大的值,弹出+记录后,继续看st[-1]是不是类似。什么时候终止while?栈空了或者不满足st[-1].值 < d, 例如334 或者4334分别对应4的时候。
  3. 这种找法所有的值都能赋上吗,或者栈中剩下什么?栈中剩下一个非严格单调减的索引序列,序列的右边没有更大的元素了,所以序列里面的索引应该对应一个设置好的初值(-1或者n)
  4. 为什么用哈希表维护不是数组?数组维护的话是索引,值和索引还是不一样的。

代码

class Solution:
    def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
        
        m, n = len(nums1), len(nums2)
        # nums2中下一个最大元素的索引
        right = dict()
        st = []
        # st中放索引还是值?
        for i, d in enumerate(nums2):
            while st and d > nums2[st[-1]]:
                top = st.pop()
                right[nums2[top]] = d
            st.append(i)

        for idx in st:
            right[nums2[idx]] = -1

        ans = []
        for d in nums1:
            ans.append(right[d])
        
        return ans

总结

  1. 找右边更大的,用单调递减栈,可以存在=的情况
  2. 维护信息的时候是弹出的时候,i或者d就是需要的信息
  3. 没有弹出的元素没有信息,需要初值或者后续维护
f2-哈希表+右到左的单调栈

基本分析

  1. 右到左需要维护的是什么?严格单调递减的栈
  2. 可以得到right的逻辑?倒序遍历,对i=n-1时候,栈是空,直接追加。其他时候,只有st[-1]严格>nums2[i]的时候,i才认老大,否则就一直踢馆,最后的结果是栈空(i对应的结果是-1),或者找到老大(st[-1])
  3. 这种情况遍历过以后还需要维护结果吗?对找不到老大的时候,认了-1了,不用再管了

代码

class Solution:
    def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
        right = dict()

        n = len(nums2)
        st = []

        for i in range(n-1, -1, -1):
            # i一直在栈里挖,想找到比他大的值
            # 不满足的时候就一直弹出来(栈里面的值都需要是自己的老大)
            while st and nums2[i] >= nums2[st[-1]]:
                st.pop()
            if st:
                right[nums2[i]] = nums2[st[-1]]
            else:
                right[nums2[i]] = -1
            st.append(i)

        ans = []
        for d in nums1:
            ans.append(right[d])
        
        return ans

总结

  1. 1是弹出的时候pop出的是索引,i是他找到的信息,可能多个弹出的结果都是i,这样一个while中可能赋值多次;2是 i一直在st中挖结果,直到挖出或者挖空以后,在while外面赋值;
  2. 前者是d > 栈顶值时候才弹栈,弹出的是严格< d的值;后者是 d >= 栈顶值的时候就弹栈。
  3. 为啥设置成这样?1弹出的时候表示i就是top要找的信息,所以对334情况,栈中可以有值相等的(1,2);对于2的情况,是i要去栈中找结果,栈就要严格递减(否则可能认错大哥,3认了右边的3)。