什么时候用到?
一维数组,寻找任何一个元素左边或者右边第一个比自己大或者校的元素,时间复杂度为O(n)
说明:
单调递增栈,从栈口到栈底的位置,元素呈现单调增的排列顺序
单调递减栈,从栈口到栈底的位置,元素呈现单调减的排列顺序
单调栈实际上也就是用空间换时间,用栈记录遍历过的元素下标;
一寻找右边第一个大的元素
从左向右维护一个单调递增栈,遍历每个元素和栈口的元素进行比较;
def dailyTemperatures(temperatures):
stack = [0]#从左向右遍历,记录一下数组第一个下标索引
answer = [0] * len(temperatures)
for i in range(1, len(temperatures)):
if temperatures[i] < temperatures[stack[-1]]:
#当前遍历的元素小于栈口的元素,可以直接加入构成一个单调增的序列
stack.append(i)
elif temperatures[i] == temperatures[stack[-1]]:
#当前遍历的元素等于栈口的元素,因为目标是要寻找右边第一个大的元素,不是大于等于的元素,所以添加到当前序列,用在后面当遇到大的元素时作差
stack.append(i)
else:
while stack and temperatures[i] > temperatures[stack[-1]]:
#如果当前遍历的元素比当前栈口索引的元素大时,直接添加则栈不能构成单调增的形式,所以需要拿出来比较并pop
#遍历的元素比栈口元素大,在原数组序列中也就意味着是该元素后面第一大的元素了,然后将两者的索引进行作差即可;
answer[stack[-1]] = i - stack[-1]
stack.pop()
stack.append(i)
return answer
temp = [73,74,75,71,69,72,76,73]
res = dailyTemperatures(temp)
print(res)
#res = [1, 1, 4, 2, 1, 1, 0, 0]
二寻找右边第一个小的元素
从左向右维护一个单调递减栈,遍历每个元素和栈口的元素进行比较;
# #寻找右边第一个小的元素
def dailyTemperatures(temperatures):
stack = [0]
answer = [0] * len(temperatures)
for i in range(1, len(temperatures)):
if temperatures[i] > temperatures[stack[-1]]:#只是在维护栈的时候注意比较对象即可
stack.append(i)
elif temperatures[i] == temperatures[stack[-1]]:
stack.append(i)
else:
while stack and temperatures[i] < temperatures[stack[-1]]:#只是在维护栈的时候注意比较对象即可
answer[stack[-1]] = i - stack[-1]
stack.pop()
stack.append(i)
return answer
temp_1 = [73,74,75,71,69,72,76,73]
res = dailyTemperatures(temp_1)
print(res)
#[3, 2, 1, 1, 0, 0, 1, 0]
三寻找左边第一个大的元素
倒序维护一个单调递增栈,遍历每个元素和栈口的元素进行比较;
def dailyTemperatures(temperatures):
stack = [len(temperatures) - 1]#倒序遍历,所以需要先加入当前数组的最后一个索引
answer = [0] * len(temperatures)
for i in range(len(temperatures) - 2, -1, -1):#倒序遍历
if temperatures[i] < temperatures[stack[-1]]:
stack.append(i)
elif temperatures[i] == temperatures[stack[-1]]:
stack.append(i)
else:
while stack and temperatures[i] > temperatures[stack[-1]]:
answer[stack[-1]] = i - stack[-1]
#answer[stack[-1]] = stack[-1] - i
stack.pop()
stack.append(i)
return answer
temp_1 = [73,74,75,71,69,72,76,73]
res = dailyTemperatures(temp_1)
print(res)
#[0, 0, 0, -1, -1, -3, 0, -1]负数表示和前一个索引的差值
#answer[stack[-1]] = stack[-1] - i运行的结果为正数,[0, 0, 0, 1, 1, 3, 0, 1]
四寻找左边第一个小的元素
倒序维护一个单调递减栈,遍历每个元素和栈口的元素进行比较;
def dailyTemperatures(temperatures):
stack = [len(temperatures) - 1]
answer = [0] * len(temperatures)
for i in range(len(temperatures) - 2, -1, -1):
if temperatures[i] > temperatures[stack[-1]]:
stack.append(i)
elif temperatures[i] == temperatures[stack[-1]]:
stack.append(i)
else:
while stack and temperatures[i] < temperatures[stack[-1]]:
answer[stack[-1]] = i - stack[-1]
#answer[stack[-1]] = stack[-1] - i
stack.pop()
stack.append(i)
return answer
temp_1 = [73,74,75,71,69,72,76,73]
res = dailyTemperatures(temp_1)
print(res)
#[0, -1, -1, 0, 0, -1, -1, -2]
#answer[stack[-1]] = stack[-1] - i:输出相应的正数间隔[0, 1, 1, 0, 0, 1, 1, 2]