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:两层循环暴力法
- 遍历nums1中的每一个元素 i i i
- 获取元素 i i i 在nums2中的索引
- 从此索引开始遍历nums2中后面的每一个元素
j
j
j
若在遍历结束之前,找到了大于 i i i 的元素 j j j,则将 j j j 入栈,且退出遍历nums2的循环;
若在遍历结束时,仍未找到大于 i i i 的元素 j j j,则将 − 1 -1 −1 入栈;
思路2:栈+哈希表
- 先忽略nums1,只对nums2操作。
- 遍历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] 入栈。 - 当栈中有多个元素时,这些元素一定为从栈顶到栈底单调递增,即每次加入的元素都比之前所有元素小,此时,若有新遍历到的元素
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[j−1]},
{ n u m s 2 [ i ] : n u m s 2 [ j − 2 ] } , \{nums2[i]: nums2[j-2]\}, {nums2[i]:nums2[j−2]},
{ n u m s 2 [ i ] : n u m s 2 [ j − 3 ] } , \{nums2[i]: nums2[j-3]\}, {nums2[i]:nums2[j−3]},
… - 此时栈为空,将 n u m s 2 [ 1 ] nums2[1] nums2[1] 入栈。
- 此时遍历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 , 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