20. 有效的括号
python
class Solution(object):
def isValid(self, s):
"""
:type s: str
:rtype: bool
"""
if len(s)%2:
return False
st = []
d = {
")":"(",
"]":"[",
"}":"{",
}
for c in s:
if c not in d:
st.append(c)
elif st and st[-1]==d[c]:
st.pop()
else:
return False
return not st
时间复杂度:O(n)
空间复杂度:O(n+∣Σ∣) # 其中 Σ 表示字符集,是哈希表的大小。
155. 最小栈
利用辅助栈存储最小元素,每当进入一个元素,就统计当前的min加入辅助栈;每当删除一个元素,就同步删除;辅助栈的每个元素代表到当前节点为止所有的最小元素【初始化一个-inf】
python
class MinStack(object):
def __init__(self):
self.stack = []
self.min_stack = [float('inf')]
def push(self, val):
"""
:type val: int
:rtype: None
"""
self.stack.append(val)
self.min_stack.append(min(val,self.min_stack[-1]))
def pop(self):
"""
:rtype: None
"""
self.stack.pop()
self.min_stack.pop()
def top(self):
"""
:rtype: int
"""
return self.stack[-1]
def getMin(self):
"""
:rtype: int
"""
return self.min_stack[-1]
所有操作的时间复杂度:O(1)
空间复杂度:O(n)
394. 字符串解码
python
class Solution(object):
def decodeString(self, s):
"""
:type s: str
:rtype: str
"""
st = []
for c in s:
if c.isdigit() or c.isalpha() or c=='[':
st.append(c)
else:
# c==']'
sub = ''
while st and st[-1].isalpha():
# 栈顶元素最后一个元素防报错
sub = st.pop()+sub # 保持原有顺序
st.pop() # 弹出[
num,d = 0,0
while st and st[-1].isdigit():
num += (int(st.pop()) * (10**d))
d += 1
sub = sub*num
st.append(sub)
return ''.join(st)
时间复杂度:O(n+S) # 解码后得到的字符串长度为S,而且其实更多的由S决定
空间复杂度:O(S) #栈中存储了中间结果,包括字母片段和数字,最终也会逐步累积成完整的解码字符串。在最坏情况下,栈内元素的总字符数接近最终结果的长度。
739. 每日温度
单调栈
可以维护一个存储下标的单调栈,从栈底到栈顶的下标对应的温度列表中的数值递减。
也就是说,对于每一个栈顶元素-1,-2的位置对应的温度会更高。【-1没有找到下一个最大元素前,-2绝对不会找到,仅仅对比栈顶即可】
当一个新的元素入栈前,如果比当前的栈顶元素来得高,那么栈顶元素对应的下一个最大元素就找到了。
python
class Solution(object):
def dailyTemperatures(self, temperatures):
res = [0 for _ in temperatures]
st = []
for i in range(len(temperatures)):
while st and temperatures[i]>temperatures[st[-1]]:
cur = st.pop()
res[cur] = i-cur
st.append(i)
return res
时间复杂度:O(n) # 对于温度列表中的每个下标,最多有一次进栈和出栈的操作。
空间复杂度:O(n) # 最差的情况就是其栈的大小恰好等于n【单调递减】
84. 柱状图中的最大矩形
维护一个存储下标的单调栈,从栈底到栈顶的下标对应的列表中的数值递增。
也就是说,对于每一个栈顶元素-1,-2的位置对应的柱子会更低。
每当我们找到了一个比栈顶元素小的元素,那么对于栈顶元素,倒数第二个元素和未入栈的元素是比当前元素小的元素,那么要算以当前栈顶元素为高的最大面积就是中间的间隔*栈顶元素的高度。
python
class Solution(object):
def largestRectangleArea(self, heights):
"""
:type heights: List[int]
:rtype: int
"""
heights =[0] + heights + [0] # 开始加0,是为了左边界不需要额外判断,右边界加0,是为了处理单调递增的数组情形
res = [] # 存储的是以每个柱子的高度所能达到的最大矩形面积
st = [] # 单调递增栈,栈底元素 -> 栈顶元素 递增(不递减)
for i in range(len(heights)):
while st and heights[i]<heights[st[-1]]:
cur = st.pop()
if not st:
# 没有元素说明cur作为左边界已经在上一轮完成了计算,栈中无元素,可以跳出while
break
left = st[-1]
s = heights[cur]*(i-left-1) # 右边小元素-左边小元素-1 就是当前柱子高度可以覆盖的最大宽度
res.append(s)
st.append(i)
return max(res) if res else 0
时间复杂度:O(n) # 对于每个下标,最多有一次进栈和出栈的操作。
空间复杂度:O(n) # 最差的情况就是其栈的大小恰好等于n【单调递增】