动态规划结束了,来到最后一块内容:单调栈了,一共就三天的内容。
通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了。时间复杂度为O(n)。
单调栈的本质是空间换时间,因为在遍历的过程中需要用一个栈来记录右边第一个比当前元素高的元素,优点是整个数组只需要遍历一次。
更直白来说,就是用一个栈来记录我们遍历过的元素,因为我们遍历数组的时候,我们不知道之前都遍历了哪些元素,以至于遍历一个元素找不到是不是之前遍历过一个更小的,所以我们需要用一个容器(这里用单调栈)来记录我们遍历过的元素。
下面进入到练习:
739. Daily Temperatures
Given an array of integers
temperatures
represents the daily temperatures, return an arrayanswer
such thatanswer[i]
is the number of days you have to wait after theith
day to get a warmer temperature. If there is no future day for which this is possible, keepanswer[i] == 0
instead.
首先想到的还是Brute Force,两层for循环,把至少需要等待的天数就搜出来了。时间复杂度是O(n^2)。
这是一道应用单调栈的题,分析的时候,要涵盖以下三种情况:
class Solution:
def dailyTemperatures(self, temperatures: List[int]) -> List[int]:
answer = [0]*len(temperatures)
stack = [0]
for i in range(1,len(temperatures)):
if temperatures[i]<=temperatures[stack[-1]]:
stack.append(i)
else:
while len(stack) != 0 and temperatures[i]>temperatures[stack[-1]]:
answer[stack[-1]]=i-stack[-1]
stack.pop()
stack.append(i)
return answer
496. Next Greater Element I
The next greater element of some element
x
in an array is the first greater element that is to the right ofx
in the same array.You are given two distinct 0-indexed integer arrays
nums1
andnums2
, wherenums1
is a subset ofnums2
.For each
0 <= i < nums1.length
, find the indexj
such thatnums1[i] == nums2[j]
and determine the next greater element ofnums2[j]
innums2
. If there is no next greater element, then the answer for this query is-1
.Return an array
ans
of lengthnums1.length
such thatans[i]
is the next greater element as described above.
要分析如下三种情况,
情况一:当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况
此时满足递增栈(栈头到栈底的顺序),所以直接入栈。
情况二:当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况
如果相等的话,依然直接入栈,因为我们要求的是右边第一个比自己大的元素,而不是大于等于!
情况三:当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况
此时如果入栈就不满足递增栈了,这也是找到右边第一个比自己大的元素的时候。
判断栈顶元素是否在nums1里出现过,(注意栈里的元素是nums2的元素),如果出现过,开始记录结果。
记录结果这块逻辑有一点小绕,要清楚,此时栈顶元素在nums2数组中右面第一个大的元素是nums2[i](即当前遍历元素)。
class Solution:
def nextGreaterElement(self, nums1: List[int], nums2: List[int]) -> List[int]:
result = [-1]*len(nums1)
stack = [0]
for i in range(1,len(nums2)):
if nums2[i]<=nums2[stack[-1]]:
stack.append(i)
else:
while len(stack)!=0 and nums2[i]>nums2[stack[-1]]:
if nums2[stack[-1]] in nums1:
index = nums1.index(nums2[stack[-1]])
result[index]=nums2[i]
stack.pop()
stack.append(i)
return result