1.有效的括号
问题:
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
方法:栈
(注意栈空和栈有余)
# 栈
def isValid(s):
Map = {'(':')', '[': ']', '{':'}'}
stack, index = [], 0
while index < len(s):
if s[index] in Map.keys(): # 入栈
stack.append(s[index])
index += 1
else: # 出栈
if not stack: # 如果为空
return False
pop_data = stack.pop() # 取出
if Map[pop_data] != s[index]: # 不匹配
return False
index += 1
if stack:
return False
return True
2.最小栈
问题:
设计一个支持 push
,pop
,top
操作,并能在常数时间内检索到最小元素的栈。
实现 MinStack
类:
MinStack()
初始化堆栈对象。void push(int val)
将元素val推入堆栈。void pop()
删除堆栈顶部的元素。int top()
获取堆栈顶部的元素。int getMin()
获取堆栈中的最小元素。
方法:
# 注意:最小值要用栈来保存(否则更新不及时)
class MinStack:
def __init__(self, nums=[]):
self.nums = nums
# self.min = float('inf') # 注意:!!! 这里需要用栈来保存最小值:如果用值来保存,元素出栈之后,最小值可能更新不及时 !!!
self.min_stack = []
def push(self, val):
self.nums.append(val)
if not self.min_stack or self.min_stack[-1] >= val:
self.min_stack.append(val)
def pop(self):
pop_val = self.nums.pop()
if pop_val == self.min_stack[-1]: # !!!更新最小值!!!
self.min_stack.pop()
return pop_val
def top(self):
if self.nums:
return self.nums[-1]
return None
def getMin(self):
if self.min_stack:
return self.min_stack[-1]
else:
return None
m_s = MinStack()
print(m_s.push(-2))
print(m_s.push(0))
print(m_s.push(-3))
print(m_s.getMin())
print(m_s.pop())
print(m_s.top())
print(m_s.getMin())
注意,这里最小值要用栈来保存,如果用值保存最小值,有元素弹出之后,会导致更新不及时。
3.字符串解码
问题:
给定一个经过编码的字符串,返回它解码后的字符串。
编码规则为: k[encoded_string]
,表示其中方括号内部的 encoded_string
正好重复 k
次。注意 k
保证为正整数。
你可以认为输入字符串总是有效的;输入字符串中没有额外的空格,且输入的方括号总是符合格式要求的。
此外,你可以认为原始数据不包含数字,所有的数字只表示重复的次数 k
,例如不会出现像 3a
或 2[4]
的输入。
方法:栈保存数字和子串
用栈保存 数字 和 之前的字符串。
开始和入栈标志:“[”(因为这时,开始记录后续字符,栈吐出的数字也是这些字符的重复次数)
# 栈
def decodeString(s):
cur_num, cur_str = 0, ''
stack = [] # 用来存 数字 和 字符串
for char in s:
if '0' <= char <= '9':
cur_num = 10 * cur_num + int(char) # 处理多位数情况
elif char == '[': # 遇到'['表示新的一轮开始,入栈(重复数字 和 之前的字符串)
stack.append((cur_num, cur_str)) # 入栈
cur_num, cur_str = 0, '' # 更新
elif char == ']':
num, pre_str = stack.pop() # 弹出栈顶的 数字(重复次数) 和 字符串(之前所有的)
cur_str = pre_str + num * cur_str # 拼接(之前的字符串 + 当前重复的)
else:
cur_str += char # 普通字符,直接拼接
return cur_str
4.每日温度
问题:
给定一个整数数组 temperatures
,表示每天的温度,返回一个数组 answer
,其中 answer[i]
是指对于第 i
天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0
来代替。
方法1:暴力(往后找)
# 方法1:暴力(往后找)
# 空间复杂度O(n^2)
def dailyTemperatures(temperatures):
res = [0] * len(temperatures)
for i in range(len(temperatures)):
for j in range(i+1, len(temperatures)):
if temperatures[i] < temperatures[j]:
res[i] = j - i
break
return res
方法2:栈(优化)
依次入栈每个元素。
比较栈顶元素与当前元素,如果栈顶小,则取出栈顶,算出差值。
# 方法2:栈(优化)
def dailyTemperatures(temperatures):
res = [0] * len(temperatures)
stack = []
for i in range(len(temperatures)):
# 比较并吐出栈顶元素 存差值
while stack and temperatures[stack[-1]] < temperatures[i]:
pre_day = stack.pop() # 吐出之前的天
res[pre_day] = i - pre_day # 存入差值
stack.append(i)
return res