题目:
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] 是如上所述的下一个更大元素 。
示例:
输入: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 。
输入: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 。
解题思路:
解法一(暴力法):
根据题意去理解题目。已知:nums1中所有元素都在nums2中,并且均无重复元素。求解的是nums1中每个元素在nums2中下一个最大的元素是啥。
第一步:生成一个列表ans初始化为m个-1。
第二步:遍历num1中元素,对于当前元素nums1[i],找到该元素在nums2中的索引位置,然后再遍历nums2中该索引号以后的元素,找到第一个比nums1[i]大的元素放进ans[i]。最后返回ans
m,n=len(nums1),len(nums2)
ans=[-1]*m
for i in range(m):
index=nums2.index(nums1[i])
k=index+1
while(k<n and nums2[k]<nums2[index] ):
k+=1
ans[i]=nums2[k] if k<n else -1
return ans
解法二(最小栈+哈希表)
该方法是以遍历nums2的方式,在哈希表中存储所有能找到下一个更大元素的元素及其更大元素。最后再遍历nums1元素,直接去哈希表中找是否存在该元素的下一个更大元素。
第一步:新建一个列表stack,用来存储从尾部往前总是比当前元素更大的元素(stack中应该是升序排列)。新建字典res存放nums2中每个元素的下一个更大元素。
第二步:从尾部开始遍历nums2,针对第一个元素,stack肯定为空,nums2[-1]是没有下一个比它大的元素,故res[num2[-1]]=-1,同时将该元素放进stack;然后取nums2中下一个元素(假设取第num个元素),如果stack中不为空,且 nums2[num] 比 stack[-1](栈顶元素,此时也是nums2最后一个元素)大,就将栈顶元素循环删除,直到栈顶元素比当前nums[num]小或stack为空。(这一步骤就是将该元素在num位置以后的元素比它小的元素都删除,只剩下比它大的元素,目的是通过这一步删除,stack中只剩下比num位置以后更大的元素,因为num位置以前的元素查找下一个更大值时要么是num元素,要么是num以后更大元素,删除后面更小元素就可减少计算量。
第三步:如果此时stack为空,说明找不到当前元素的下一个更大元素,故res[num]=-1;如果不为空,栈顶元素就应该是下一个更大元素,即赋值即可。
最后,遍历nums1,去哈希表中找该元素的下一个更大元素。
res = {}
stack = []
for num in reversed(nums2):
while stack and num >= stack[-1]:
stack.pop()
res[num] = stack[-1] if stack else -1
stack.append(num)
return [res[nums] for nums in nums1]
可参考官方力扣图片步骤。
知识:
reversed(nums2)表示从列表尾部往前依次遍历列表。我使用的range(0,len(nums2),-1)应该也没毛病。
思考:
无论是找下一个更大还是更小,都可以通过使用栈来进行删除不符合的元素,也就是在遍历元素时进行第一遍筛选,当找下一个元素的更大或更小值时,需要对比的计算量就会减少。该思路还可进一步练习,力扣739.每日温度,42.接雨水,503.下一个更大II,456.132模式