【力扣刷题】496. 下一个更大元素 I (暴力法+最小栈)

题目:

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模式

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值