stack的主要特征只有一句就是后进先出。
在解决问题中主要用于和顺序有关的问题。在现实世界中比如:
示例我选择这个例子string = “azxxzy”,移除后的结果是“ay”,中间看似两个z是不相邻的,但是移除了x之后两个就相邻了这也是满足条件的。
实现步骤:
代码实现:
def remove_duplicates(string):
stack = []
for c in string:
# need to check if stack is not empty
if stack and c == stack[-1]:
stack.pop()
else:
stack.append(c)
return "".join(stack)
学习笔记:
在题解中谈到,naive的做法,是找到所有的小写字母的双对比如aa,bb,之类的,所有的二十六个字母的组合,每次删掉其中的重复后继续遍历删除,直到无法删除为止。虽然所有组合也只有26个,但是时间复杂度会达到n的平方,相比较stack是一种很简单并且容易想到的方法,所以并没有必要这么做。总之这是一道很简单的题,它的时间复杂度和空间复杂度都是O(n)。
使用stack结构构架一个队列。
队列的性质,先入先出。
需要实现以下方法:
实现push方法的步骤:两个stack
已有stack:
class Stack:
def __init__(self):
self.stack_list = []
def is_empty(self):
return len(self.stack_list) == 0
def top(self):
if self.is_empty():
return None
return self.stack_list[-1]
def size(self):
return len(self.stack_list)
def push(self, value):
self.stack_list.append(value)
def pop(self):
if self.is_empty():
return None
return self.stack_list.pop()
主代码练习:
from stack import Stack
class MyQueue(object):
def __init__(self):
self.queue = Stack()
def push(self, x):
stack = Stack()
if self.queue.is_empty():
self.queue.push(x)
else:
for i in range(self.queue.size()):
stack.push(self.queue.pop())
self.queue.push(x)
for i in range(stack.size()):
self.queue.push(stack.pop())
def pop(self):
return self.queue.pop()
def peek(self):
return self.queue.top()
def empty(self):
return self.queue.is_empty()
学习笔记:很顺利,基本没卡壳,活用给出的stack数据结构就行了。答案题解如下,直接在初始中构架两个stack,默认stack1为结果队列。中间遍历使用了while,一开始我也想用的,但还是选了for哈哈。最后那个判断空的结构,如果是用了while就不需要的,答案很好!时间复杂度除了push是n,其他都是常数。
from stack import Stack
class MyQueue(object):
# constructor to initialize two stacks
def __init__(self):
self.stack1 = Stack()
self.stack2 = Stack()
def push(self, x):
while not self.stack1.is_empty():
self.stack2.push(self.stack1.pop())
self.stack1.push(x)
while not self.stack2.is_empty():
self.stack1.push(self.stack2.pop())
def pop(self):
return self.stack1.pop()
def peek(self):
return self.stack1.top()
def empty(self):
return self.stack1.is_empty()
计算器计算问题。给一个有效的计算公式字符串s,计算结果。
操作顺序:首先将连续的数字字符转化为数字,然后处理加号和减号,最后处理括号。
过程梳理:
代码练习:
def calculator(s):
stack = []
number = 0
sign_value = 1
result = 0
for char in s:
if char.isdigit():
number = number * 10 + int(char)
elif char == '+':
result += sign_value * number
number = 0
sign_value = 1
elif char == '-':
result += sign_value * number
number = 0
sign_value = -1
elif char == '(':
stack.append(result)
stack.append(sign_value)
# reset
result = 0
sign_value = 1
elif char == ')':
result += sign_value * number
number = 0
result *= stack.pop() # sign_value
result += stack.pop() # previous result
result += sign_value * number
return result
答案题解代码:
def calculator(expression):
number = 0
sign_value = 1
result = 0
operations_stack = []
for c in expression:
if c.isdigit():
number = number * 10 + int(c)
if c in "+-":
result += number * sign_value
sign_value = -1 if c == '-' else 1
number = 0
elif c == '(':
operations_stack.append(result)
operations_stack.append(sign_value)
result = 0
sign_value = 1
elif c == ')':
result += sign_value * number
pop_sign_value = operations_stack.pop()
result *= pop_sign_value
second_value = operations_stack.pop()
result += second_value
number = 0
return result + number * sign_value
学习笔记:我觉得这个题对我算法小菜鸡来说挺难的,尤其是中间的多次符号重新初始化操作,需要很清晰的逻辑。由于是遍历了整个字符串,所以时间复杂度是O(n)。