栈和队列 496. 下一个更大元素I 503.下一个更大元素II 739.每日温度

496. 下一个更大元素I

  • 给定两个没有重复元素的数组 nums1 和 nums2 ,其中nums1 是 nums2 的子集。找到 nums1 中每个元素在 nums2 中的下一个比其大的值。
    nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出-1。

示例:

输入: nums1 = [4,1,2], nums2 = [1,3,4,2].
输出: [-1,3,-1]
解释:
    对于num1中的数字4,你无法在第二个数组中找到下一个更大的数字,因此输出 -1。
    对于num1中的数字1,第二个数组中数字1右边的下一个较大数字是 3。
    对于num1中的数字2,第二个数组中没有下一个更大的数字,因此输出 -1。

思路1:两层循环暴力法

  1. 遍历nums1中的每一个元素 i i i
  2. 获取元素 i i i 在nums2中的索引
  3. 从此索引开始遍历nums2中后面的每一个元素 j j j
    若在遍历结束之前,找到了大于 i i i 的元素 j j j,则将 j j j 入栈,且退出遍历nums2的循环;
    若在遍历结束时,仍未找到大于 i i i 的元素 j j j,则将 − 1 -1 1 入栈;

思路2:栈+哈希表

  1. 先忽略nums1,只对nums2操作。
  2. 遍历nums2,首先将 n u m s 2 [ 1 ] nums2[1] nums2[1] 入栈,随后对于第二个元素 n u m s 2 [ 2 ] nums2[2] nums2[2],判断其是否比 n u m s 2 [ 1 ] nums2[1] nums2[1] 大:
    n u m s 2 [ 2 ] < n u m s 2 [ 1 ] nums2[2]<nums2[1] nums2[2]<nums2[1],则将 n u m s 2 [ 2 ] nums2[2] nums2[2] 也入栈;
    n u m s 2 [ 2 ] > n u m s 2 [ 1 ] nums2[2]>nums2[1] nums2[2]>nums2[1],则将 n u m s 2 [ 1 ] nums2[1] nums2[1] 出栈,二者构成映射关系放入哈希表: { n u m s 2 [ 1 ] : n u m s 2 [ 2 ] } \{nums2[1]: nums2[2]\} {nums2[1]:nums2[2]},并将 n u m s 2 [ 2 ] nums2[2] nums2[2] 入栈。
  3. 当栈中有多个元素时,这些元素一定为从栈顶到栈底单调递增,即每次加入的元素都比之前所有元素小,此时,若有新遍历到的元素 n u m 2 [ i ] > num2[i]> num2[i]> 栈顶元素 n u m 2 [ j ] num2[j] num2[j]
    n u m s 2 [ i ] nums2[i] nums2[i] 与栈中所有元素构成映射关系放入哈希表,直至栈为空,因为此时 n u m s 2 [ i ] nums2[i] nums2[i] 大于栈中所有元素:
    { n u m s 2 [ i ] : n u m s 2 [ j ] } , \{nums2[i]: nums2[j]\}, {nums2[i]:nums2[j]}
    { n u m s 2 [ i ] : n u m s 2 [ j − 1 ] } , \{nums2[i]: nums2[j-1]\}, {nums2[i]:nums2[j1]}
    { n u m s 2 [ i ] : n u m s 2 [ j − 2 ] } , \{nums2[i]: nums2[j-2]\}, {nums2[i]:nums2[j2]}
    { n u m s 2 [ i ] : n u m s 2 [ j − 3 ] } , \{nums2[i]: nums2[j-3]\}, {nums2[i]:nums2[j3]}
  4. 此时栈为空,将 n u m s 2 [ 1 ] nums2[1] nums2[1] 入栈。
  5. 此时遍历nums1,将每一个元素作为键,在哈希表(字典)中找到映射(值),并添加到结果列表中,未找到的键,设-1为默认值。

代码实现1:

class Solution:
    def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
        lst = []
        for i in nums1:
        	# 获取i在nums2中的索引,并切片
            for j in nums2[nums2.index(i):]:
                if j>i:
                    lst.append(j)
                    break
                if j == nums2[-1]:
                    lst.append(-1)
                
        return lst

代码实现2:

class Solution:
    def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
        stack, hash_map = [], {}
        ret = []
        for n2 in nums2:
        	# 当栈中有元素,且新遍历到的值大于栈顶元素时,建立哈希映射
            while stack and n2 > stack[-1]:
                hash_map[stack.pop()] = n2
            # 栈中没有元素,或新遍历到的值小于栈顶元素时,入栈
            stack.append(n2)

        for n1 in nums1:
        	# 遍历nums1中所有元素,作为字典的键,寻找对应的值追加到结果列表中,若匹配不到键,则设-1为值
            ret.append(hash_map.get(n1, -1))
            
        return ret

503. 下一个更大元素II

  • 给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。

示例:

输入: [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数; 
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。

思路:

本题与上一题有两个不同之处:

  1. 本题数组中元素可以重复,因此不能将元素的值作为哈希表的键,需要取其索引,即栈中存放的不是数组的元素,而是元素对应的索引。
  2. 本题涉及循环一次,由于我们只需要找出下一个更大的数,而不是索引,因此可将数组长度变为原来的两倍,即 [ 1 , 2 , 1 , 3 , 4 , 1 ] [1, 2, 1, 3, 4, 1] [1,2,1,3,4,1] 变为 [ 1 , 2 , 1 , 3 , 4 , 1 , 1 , 2 , 1 , 3 , 4 , 1 ] [1, 2, 1, 3, 4, 1, 1, 2, 1, 3, 4, 1] [1,2,1,3,4,1,1,2,1,3,4,1],使用上题相同原理遍历加长的数组即可获得答案。

代码实现:

class Solution:
    def nextGreaterElements(self, nums: List[int]) -> List[int]:
        stack, hashmap = [], {}
        ret = []
        # 将数组加长一倍
        cur = nums+nums
        
        for n in range(len(cur)):
        	# 若栈不为空,且遍历到的当前索引对应的值大于栈中索引对应的值,则将栈中索引和当前值构成映射,放入哈希表。
            while stack and cur[n] > cur[stack[-1]]:
                hashmap[stack.pop()] = cur[n]
            stack.append(n)

        for i in range(len(nums)):
            ret.append(hashmap.get(i, -1))

        return ret

739. 每日温度

  • 根据每日 气温 列表,请重新生成一个列表,对应位置为天数,是需要再等待多久,温度才会超过该日的天数。如果之后都不会升高,请在该位置用 0 来代替。
    例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。
    提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。

思路:

从题目来看,最终的输出是一个天数差,因此可以想到是索引差,思路同前两题,只不过在构建哈希表映射是需要有一点改动,即栈顶元素(索引)作为键,当前索引与栈顶元素的差(索引差)作为值。
总结:第一题是值的映射,第二题是索引与值的映射,第三题是索引与索引的映射。

代码实现:

class Solution:
    def dailyTemperatures(self, T: List[int]) -> List[int]:
        stack, hashmap = [], {}
        ret = []
        for i, t in enumerate(T):
            while stack and t > T[stack[-1]]:
                top = stack.pop()
                hash_map[top] = i-top
            stack.append(i)
        
        for i in range(len(T)):
            ret.append(hashmap.get(i, 0))
        
        return ret
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值