单调栈(Monotone stack):一种特殊的栈,在先进先出的基础上,要求从top到bottom的元素是单调的(单调递增 or 单调递减)
0x01 理解单调栈
维护一个单调栈的过程如图:
单调栈过程
单调栈可以解决的问题包括:
寻找左侧第一个比当前元素大的元素
寻找左侧第一个比当前元素小的元素
寻找右侧第一个比当前元素大的元素
寻找右侧第一个从当前元素小的元素
单调栈思路模版
1 2 3 4 5 6 7
stack = [] for num in nums: while stack andrule(stack[-1],num): # rule should be defined stack.pop() stack.push(gen(num)) # gen should be related to the num
classSolution(object): defcarFleet(self, target, position, speed): cars = sorted(zip(position, speed)) times = [float(target - p) / s for p, s in cars] ans = 0 whilelen(times) > 1: lead = times.pop() if lead < times[-1]: ans += 1# if lead arrives sooner, it can't be caught else: times[-1] = lead # else, fleet arrives at later time 'lead'
return ans + bool(times) # remaining car is fleet (if it exists)
def singleStack(arr,left): stack = [] for i in range(len(arr)): while stack and arr[stack[-1]]>=arr[i]: # 当存在的时候 stack.pop() stack.append(i) iflen(stack)==1: left[i] = stack[0]+1 else: left[i] = stack[-1]-stack[-2] returnleft
def singleStack2(arr,left): stack = [] for i in range(len(arr)): while stack and arr[stack[-1]]>arr[i]: # 当存在的时候 stack.pop() stack.append(i) iflen(stack)==1: left[i] = stack[0]+1 else: left[i] = stack[-1]-stack[-2] returnleft
# how ever, this will make the duplicated # only one way stack is accpted left = singleStack(arr,left_1) right = singleStack2(arr[::-1],right_1)[::-1] res = 0 for i in range(len(arr)): res+=arr[i]*left[i]*right[i] returnres%MOD
classSolution: deffind132pattern(self, nums: List[int]) -> bool: ak = float("-inf") stack = [] for num inreversed(nums): if ak > num: returnTrue while stack and stack[-1] < num: ak = stack.pop() stack.append(num) returnFalse
class Solution: def maximumSumOfHeights(self, maxHeights: List[int]) -> int: # 自左向右建立单调栈 n = len(maxHeights) suffix = [0]*(n+1) presum = [0]*(n+1) stack = [] # 根据单调栈求前缀和 for i in range(n): while stack and maxHeights[stack[-1]] > maxHeights[i]: stack.pop() j = stack[-1] if stack else -1 # i 目标前缀和的下标 # j 是左侧第一个比目标值小的元素,也就是下山的元素 presum[i+1] = presum[j+1]+(i-j)*maxHeights[i] stack.append(i)
stack = [] # 根据单调栈求后缀和 for i in range(n-1,-1,-1): while stack and maxHeights[stack[-1]] > maxHeights[i]: stack.pop() j = stack[-1] if stack else n suffix[i] = suffix[j]+(j-i)*maxHeights[i] stack.append(i)
# 合并 res = 0 for i in range(n): res = max(res,presum[i+1]+suffix[i]-maxHeights[i]) return res