- 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]