Leetcode 496 下一个更大元素 (栈)+单调栈通用做法

一但要求下一个更大的元素,就是用单调栈解更好
这个题考虑nums1中对应的nums2相同元素的后面寻找值更大的数
相当于是遍历nums2后面的元素 寻找大于nums1[i]的数字并保留
模式识别:【后入先出】>>>>栈
模式识别:求前/后的第一个最大/小元素 >>>>>单调栈
通常是一维数组,要寻找任一元素右边(左边)第一个比自己大(小)的元素,且要求 O(n) 的时间复杂度

在这里插入图片描述

解法1 究极复杂法


class Solution:
    def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
        result = []
        for i in range(len(nums1)):
            for j in range(len(nums2)): #遍历

                if nums1[i]==nums2[j]: #找nums1[i]==nums2[j]
                    if j == len(nums2)-1 and nums2[j]<=nums1[i]: 
                        result.append(-1)
                    else:
                        for p in range(1,len(nums2)-j):
                            if j+p <= len(nums2)-1: #j存在
                                if nums2[j+p]>nums1[i]:
                                    result.append(nums2[j+p])
                                    break
                                elif nums2[j+p]<=nums1[i] and p==len(nums2)-j-1:
                                    result.append(-1)
                                    break

                            else: 
                                result.append(-1)
                                break
                        
                        j = 0
                        break
                
        return result
           
    

解法2 用两个栈去做

用两个栈 nums2入栈,弹出的元素入temp栈保存,之后重复上述过程
# 遍历nums1,之后nums2出栈比对大小 top = stack.pop()和nums1[i]
# 若相等则停止出栈,恢复temp中的元素到stack内,
# 若top>nums1[i],则令max = top,继续寻找
# 若top<nums1[i],则继续寻找
# 最终遍历结束 输出max的list即可

 class Solution:
    def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
    # time complexity O(MN)
    # space complexity O(2N)=O(N)
        # 用两个栈 nums2入栈,弹出的元素入temp栈保存
        # 遍历nums1,之后nums2出栈比对大小 top = stack.pop()和nums1[i] 
            # 若相等则停止出栈,恢复temp中的元素到stack内,
            # 若top>nums1[i],则令max = top,继续寻找
            # 若top<nums1[i],则继续寻找
        # 最终遍历结束 输出max的list即可

        max = -1
        final = []
        stack = []
        temp = []
        for i in nums2:
            stack.append(i) #nums2中的元素入栈

        for num in nums1:
            while len(nums2)!=0:
                temnum = stack.pop() #nums2元素出栈
                temp.append(temnum) #temnum入栈temp保存
                if temnum==num: # 相等停止出栈 遍历下一个num1
                    break
                elif temnum > num: # temnum大于num 保存max
                    max = temnum
                else:              # temnum小于num 不执行操作
                    continue
            final.append(max)
            max = -1
            for m in range(len(temp)):
                stack.append(temp.pop())
        
        return final
                

解法3 暴力解法

在这里插入图片描述

class Solution:
    def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
        m,n = len(nums1),len(nums2)
        result = [0]*m
        for i in  range(m):
            j = nums2.index(nums1[i]) # 寻找nums2中和nums1相同元素的index 【nums1是nums2的子集】
            k = j+1
            while k<n and nums2[k]<nums2[j]: # 当k小于len(nums2) and nums2[k]<nums2[j]=nums1[i]时 再向→找下一个
                k +=1
            result[i] = nums2[k] if k<n else -1
        return result

                

在这里插入图片描述

解法4 单调栈☆

单调递增栈:从 栈底 到 栈顶 递增,栈顶大
单调递减栈:从 栈底 到 栈顶 递减,栈顶小

 # nums2 →遍历 存每个元素右边第一个最大值进哈希表
# 方法:维护单调【递减】栈(栈底>>>栈顶,大>>>小,从而找到右边第一个比自己大的元素)
        # 维护单调递减栈:1)遇到[当前元素] 大于 [栈顶元素top = stack.pop()] 时:  栈顶元素出栈,当前元素进栈
        # 2)遇到[当前元素] 小于 [栈顶元素top = stack.pop()] 时:[当前元素]压入栈
        # 3)最终清算栈内仍然留存的元素 赋-1(右边没有比这些元素的大的了)
# nums1中对应的nums2的元素 查哈希表 输出

# time complexity O()
# space complexity O()

class Solution:
    def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
        res = {}
        stack = []
        # a = []
        
        for num in nums2:
            while stack and num > stack[-1]:  # 当前元素大于栈顶元素时且栈内还有元素时: 弹出栈顶元素>>记录信息>>当前元素入栈
                top = stack.pop() # 弹出栈顶元素
                res[top] = num  # 生成哈希表 key:元素  value:右边第一个最大的数值
            stack.append(num) # 入栈



        while stack:    # 如果stack中还有元素 >>>弹出至空为止
            res[stack.pop()] = -1   # 生成哈希表 key:元素  value:-1
        return [res[num] for num in nums1]  # 遍历nums1 从之前nums2生成出来的哈希表中寻找对应key的结果,并合并为列表输出【好方法】

      
                

结尾方法2【最好】

return [res.get(x, -1) for x in nums1]

结尾方法3

for n in nums1: # 遍历nums1 从之前nums2生成出来的哈希表中寻找对应key的结果,并合并为列表输出 【方法二】
     a.append(res[n])
return a

寻找右边第一个最大的数

# 当前项向 右 找第一个比自己大的位置 —— 从左向右 维护一个单调递 减 栈
def nextGreaterElement(nums):
    stack = []
    res = {i: -1 for i in nums}
    for num in nums:
        while stack and num > stack[-1]:  # 当前元素大于栈顶元素时且栈内还有元素时: 弹出栈顶元素>>记录信息>>当前元素入栈
            top = stack.pop()  # 弹出栈顶元素
            res[top] = num  # 生成哈希表 key:top 元素  value:num 右边第一个最大的数值
        stack.append(num)  # 当前元素入栈
    return res

寻找右边第一个最小的数

# 当前项向 右 找第一个比自己小的位置 —— 从左向右 维护一个单调递 增 栈
def nextGreaterElement(nums):
    stack = []
    res = {i: -1 for i in nums}
    for num in nums:
        while stack and num < stack[-1]:  # 当前元素小于栈顶元素时且栈内还有元素时: 弹出栈顶元素>>记录信息>>当前元素入栈
            top = stack.pop()  # 弹出栈顶元素
            res[top] = num  # 生成哈希表 key:top 元素  value:num 右边第一个最小的数值
        stack.append(num)  # 当前元素入栈
    return res

寻找左边第一个最大的数

# 当前项向 左 找第一个比自己大的位置 —— 从右向左 维护一个单调递 减 栈
def nextGreaterElement(nums):
    stack = []
    res = {i: -1 for i in nums}
    for num in reversed(nums):  # 从右向左
        while stack and num > stack[-1]:  # 当前元素大于栈顶元素时且栈内还有元素时: 弹出栈顶元素>>记录信息>>当前元素入栈
            top = stack.pop()  # 弹出栈顶元素
            res[top] = num  # 生成哈希表 key:top 元素  value:num 左边第一个最大的数值
        stack.append(num)  # 当前元素入栈
    return res

寻找左边第一个最小的数

# 当前项向 左 找第一个比自己小的位置 —— 从右向左 维护一个单调递 增 栈
def nextGreaterElement(nums):
    stack = []
    res = {i: -1 for i in nums}
    for num in reversed(nums):  # 从右向左
        while stack and num < stack[-1]:  # 当前元素小于栈顶元素时且栈内还有元素时: 弹出栈顶元素>>记录信息>>当前元素入栈
            top = stack.pop()  # 弹出栈顶元素
            res[top] = num  # 生成哈希表 key:top 元素  value:num 左边第一个最小的数值
        stack.append(num)  # 当前元素入栈
    return res
nums = [4, 3, 5, 1, 2, 6]
result = nextGreaterElement(nums)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值