什么是单调栈?
顾名思义就是栈内元素单调按照递增(递减)顺序排列的栈。
单调栈应用一
给一个无重复值的数组,依次计算数组中每个数的左边和右边比这个数小、且离这个数最近的位置,没有时用None表示。返回每个数的左右邻居下标。
如果是有重复值的数组,又该怎么实现呢?
有重复值时,栈内元素需要存储为链表,相同的值,依次追加到链表上,统一结算。
要求时间复杂度为O(N)
单调栈应用二
给定一个只包含正数的数组arr,arr中任何一个子数组sub,
一定都可以算出(sub累加和 )* (sub中的最小值)是什么,
那么所有子数组中,这个值最大是多少?
代码
class MonotonousStack:
"""
单调栈
给一个无重复值的数组,依次计算数组中每个数的左边和右边比这个数小、且离这个数最近的位置,没有时用None表示
返回每个数的左右邻居下标
要求时间复杂度为O(N)
"""
def solution(self, arr):
"""
:param arr: [3,5,2,4,7,6]
:return:
"""
dc = dict()
stack = [0]
for i in range(1, len(arr)):
while stack and arr[stack[-1]] > arr[i]:
idx = stack.pop()
if stack:
dc[idx] = [stack[-1], i]
else:
dc[idx] = [None, i]
stack.append(i)
while stack:
idx = stack.pop()
if stack:
dc[idx] = [stack[-1], None]
else:
dc[idx] = [None, None]
return dc
def solution1(self, arr):
"""
有重复值
:param arr: [5,4,3,4,5,3,5,6]
:return:
"""
dc = dict()
stack = [[0]]
for i in range(1, len(arr)):
while stack and arr[stack[-1][0]] >= arr[i]:
if arr[stack[-1][0]] == arr[i]:
stack[-1].append(i)
break
linkedlist = stack.pop()
for idx in linkedlist:
if stack:
dc[idx] = [stack[-1][0], i]
else:
dc[idx] = [None, i]
stack.append([i])
while stack:
linkedlist = stack.pop()
for idx in linkedlist:
if stack:
dc[idx] = [stack[-1][0], None]
else:
dc[idx] = [None, None]
return dc
def solution2(self, arr):
"""
给定一个只包含正数的数组arr,arr中任何一个子数组sub,
一定都可以算出(sub累加和 )* (sub中的最小值)是什么,
那么所有子数组中,这个值最大是多少?
:param arr: [5,3,2,1,6,7,8,4]
:return:
"""
ans = 0
stack = [0]
for i in range(1, len(arr)):
while stack and arr[stack[-1]] > arr[i]:
idx = stack.pop()
if stack:
ans = max(ans, arr[idx]*sum(arr[stack[-1]+1:i]))
else:
ans = max(ans, arr[idx] * sum(arr[0:i]))
stack.append(i)
while stack:
idx = stack.pop()
if stack:
ans = max(ans, arr[idx] * sum(arr[stack[-1] + 1:len(arr)]))
else:
ans = max(ans, arr[idx] * sum(arr[0:len(arr)]))
return ans