下一个更大元素 I (python)

  • nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置 右侧 的 第一个 比 x 大的元素。
  • 两个 没有重复元素的数组 nums1 和 nums2 ,下标从 0 开始计数,其中nums1 是 nums2 的子集
  • 对于每个 0 <= i <nums1.length ,找出满足 nums1[i] == nums2[j] 的下标 j ,并且在 nums2 确定 nums2[j]的 下一个更大元素 。如果不存在下一个更大元素,那么本次查询的答案是 -1 。
  • 返回一个长度为 nums1.length 的数组 ans作为答案,满足 ans[i] 是如上所述的 下一个更大元素 。

示例 1:

输入:nums1 = [4,1,2], nums2 = [1,3,4,2]. 输出:[-1,3,-1] 解释:nums1
中每个值的下一个更大元素如下所述:

  • 4 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。
  • 1 ,用加粗斜体标识,nums2 = [1,3,4,2]。下一个更大元素是 3 。
  • 2 ,用加粗斜体标识,nums2 = [1,3,4,2]。不存在下一个更大元素,所以答案是 -1 。

示例 2:

输入:nums1 = [2,4], nums2 = [1,2,3,4]. 输出:[3,-1] 解释:nums1
中每个值的下一个更大元素如下所述:

  • 2 ,用加粗斜体标识,nums2 = [1,2,3,4]。下一个更大元素是 3 。
  • 4 ,用加粗斜体标识,nums2 = [1,2,3,4]。不存在下一个更大元素,所以答案是 -1 。

提示:

  • 1 <= nums1.length <= nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 104
  • nums1和nums2中所有整数 互不相同
  • nums1 中的所有整数同样出现在 nums2 中

思路一:暴力求解
遍历两个数组,在数组2中先找到相等的数,继续遍历数组2,找到第一大的数,若遍历完数组2没有找到,则返回 -1

def nextGreaterElement(nums1, nums2):
    re = []
    for i in range(len(nums1)):
        flag, flag1 = 0, 0  # 用于标记是否找到相等的数、是否找到右边第一个最大的数
        tmp = -1
        for j in range(len(nums2)):
            if flag == 0 and nums1[i] == nums2[j]:
                flag = 1
                tmp = nums2[j]
            if flag == 1 and nums2[j] > tmp:
                re.append(nums2[j])
                flag1 = 1
                break
        if flag1 == 0:  # 没找到返回-1
            re.append(-1)
    return re

思路二:单调栈
单调栈(Monotonic Stack)是一种特殊的栈结构,其核心在于维护栈内元素的单调性​(递增或递减)。它通过巧妙的入栈和出栈规则,使得栈内元素始终保持有序,从而高效解决一类与元素顺序相关的问题。
单调栈的关键点在于维护栈的单调性,每次处理元素时保持这种单调性,同时在处理过程中可以得到需要的结果。

  • 递增栈:栈底到栈顶元素单调递增(栈顶最大)。 适用场景:寻找某个元素左侧/右侧第一个更小的元素。
  • 递减栈:栈底到栈顶元素单调递减(栈顶最小)。 适用场景:寻找某个元素左侧/右侧第一个更大的元素。

​操作规则​:遍历数组时,对每个元素进行以下操作:

  • 弹出破坏单调性的元素:若当前元素与栈顶元素的关系破坏单调性(如递增栈中遇到更小的元素),则持续弹出栈顶,直到满足单调性。
  • ​记录结果:在弹出后,触发结果的记录(如找到更大/更小元素)。
  • ​压入当前元素:确保新元素入栈后,栈仍然保持单调性。

单调递减栈,由于是找到右边最大的数,从右向左遍历结果更直观输出:

def mstack(nums1, nums2):
    stack = []
    re = {}
    for num in reversed(nums2): # 倒序遍历
        while stack and num >= stack[-1]:  # 当前元素大于栈顶元素时,将栈顶元素出栈
            stack.pop()
        re[num] = stack[-1] if stack else -1  # 栈顶元素即是第一个最大元素
        stack.append(num)
    return [re[num] for num in nums1] # 使用哈希返回结果

也可以从左到右遍历,但是判断逻辑则发生改变:

def mstack1(nums1, nums2):
    result = {}
    stack = []
    for num in nums2:
        # 当前元素比栈顶元素大时,栈顶元素的右侧第一个更大元素则为当前元素
        while stack and num >= stack[-1]:
            top = stack.pop()
            result[top] = num
        stack.append(num)
    for num in stack:  # 未出栈则没有大于的元素
        result[num] = -1
    return [result[num] for num in nums1]

从左到右遍历时,单调栈内存放元素索引:

def mstack2(nums1, nums2):
    stack = []
    re = [-1] * len(nums2)
    for i in range(len(nums2)):
        # 当前元素比栈顶大时,栈顶元素的右侧更大元素确定为当前元素
        while stack and nums2[i] >= nums2[stack[-1]]:
            top = stack.pop()
            re[top] = nums2[i]
        stack.append(i)
    result = dict(zip(nums2, re))
    return [result[num] for num in nums1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值