代码随想录|栈与队列 232.用栈实现队列,20.有效的括号,逆波兰表达式求值,239. 滑动窗口最大值
python
队列和栈,不能做迭代遍历,因此不是容器,是容器适配器
一、232.用栈实现队列
class MyQueue:
def __init__(self):
self.stackin=[]
self.stackout=[]
def push(self, x):
self.stackin.append(x)
def pop(self):
if self.empty():
return None
if self.stackout:
return self.stackout.pop()
else:
for i in range(len(self.stackin)):
self.stackout.append(self.stackin.pop())
return self.stackout.pop()
def peek(self) -> int:
x=self.pop()
self.stackout.append(x)
return x
def empty(self) -> bool:
return not (self.stackin or self.stackout)
列表可以直接表示队列,append表示push,pop表示pop(先出最后一个元素)
二、225.用队列实现栈
队列——需要能取头部元素——需要引入deque()的popleft功能
是否为空,是定义出来的,list和que并不自带
思路上:把尾部之前的内容都剪切到尾部之后
1.核心代码
from collections import deque
class MyStack:
def __init__(self):
self.que=deque()
def push(self, x: int) -> None:
self.que.append(x)
def pop(self) :
if self.empty():
return None
for i in range(len(self.que)-1):
self.que.append(self.que.popleft())
return self.que.popleft()
def top(self):
x=self.pop()
self.que.append(x)
return x
def empty(self) :
return not self.que
2.输入输出
from collections import deque
import ast
class MyStack:
def __init__(self):
self.que=deque()
def push(self, x: int) -> None:
self.que.append(x)
def pop(self) :
if self.empty():
return None
for i in range(len(self.que)-1):
self.que.append(self.que.popleft())
return self.que.popleft()
def top(self):
x=self.pop()
self.que.append(x)
return x
def empty(self) :
return not self.que
if __name__=="__main__":
command=ast.literal_eval(input())
argument=ast.literal_eval(input())
mystack=MyStack()
result=[]
for cmd,arg in zip(command,argument):
if cmd=="MyStack":
result.append(None)
if cmd=="push":
mystack.push(arg)
result.append(None)
if cmd=="pop":
result.append(mystack.pop())
if cmd=="top":
result.append(mystack.top())
if cmd=="empty":
result.append(mystack.empty())
print(result)
三、20.有效的括号
1.核心代码
注意存栈的时候存另一半就可以了
# 方法一,仅使用栈,更省空间
class Solution:
def isValid(self, s: str) -> bool:
stack = []
for item in s:
if item == '(':
stack.append(')')
elif item == '[':
stack.append(']')
elif item == '{':
stack.append('}')
elif not stack or stack[-1] != item:
return False
else:
stack.pop()
return True if not stack else False
这行代码是有效括号检验算法的关键部分。这里的 elif 语句是在遍历输入字符串 s 每个字符的循环中。对于遇到的每个闭括号字符()、]、}),此 elif 分支会检查两个条件:
not stack:确保栈不为空。如果栈为空,但是循环遇到了一个闭括号,那意味着没有相对应的开括号,因此返回 False。
stack[-1] != item:检查栈顶元素是否与当前字符匹配。stack[-1] 是获取栈顶元素的方式。如果栈顶元素与当前遍历到的闭括号不匹配,则返回 False。这是因为每个开括号应该与其相对应的闭括号顺序匹配。例如,如果上一个开括号是 {,但当前字符是 ),则括号是不匹配的。
当你想在列表末尾添加元素时,你应该使用 append()。而当你想在集合中添加一个唯一元素时,你应该使用 add()。记住,尝试使用 add() 在列表中添加元素会导致 AttributeError,因为 list 对象没有 add() 方法。同样的,使用 append() 添加元素到集合会导致 AttributeError,因为 set 对象没有 append() 方法。
与c++的不同:取栈顶为stack[-1]
2.输入输出
def isValid(s):
stack=[]
for item in s:
if item =='(':
stack.append(')')
elif item=='{':
stack.append('}')
elif item=='[':
stack.append(']')
elif not stack or stack[-1]!=item:
return False
else:
stack.pop()
return not stack
if __name__=="__main__":
s=input()
ss=isValid(s)
print(ss)
3、二刷 20240812
class Solution:
def isValid(self, s: str) -> bool:
save=[]
for ss in s:
if ss=="(":
save.append(")")
elif ss=="[":
save.append("]")
elif ss=="{":
save.append("}")
elif (not save) or ss!=save[-1]:
return False
else:
save.pop()
if save:
return False
else:
return True
if __name__=="__main__":
s=input()
solution=Solution()
result=solution.isValid(s)
print(result)
四、1047.删除字符串中所有重复项
class Solution:
def removeDuplicates(self, s: str) -> str:
save=[]
for ss in s:
if not save:
save.append(ss)
elif ss==save[-1]:
save.pop()
elif ss!=save[-1]:
save.append(ss)
return "".join(save)
很简单,一点都不难,用栈
然后记住把最后返回要把字符串拼接,就行了!!
四、逆波兰表达式求值
from operator import add, sub, mul
class Solution:
op_map = {'+': add, '-': sub, '*': mul, '/': lambda x, y: int(x / y)}
def evalRPN(self, tokens: List[str]) -> int:
stack = []
for token in tokens:
if token not in {'+', '-', '*', '/'}:
stack.append(int(token))
else:
op2 = stack.pop()
op1 = stack.pop()
stack.append(self.op_map[token](op1, op2)) # 第一个出来的在运算符后面
return stack.pop()
map的表达方式{‘+’:add,}
函数里有自变量的表达方式 lambda x,y:int(x/y)
s.replace(‘"’, ‘’)移除引号再可以化为整数
2、输入输出
这边输入输出碰到了很大的问题,“”双引号好像不太好去掉,而且必须在第一次输入的时候就去掉
from typing import List
from operator import add,sub,mul
class Solution:
op_map = {'+': add, '-': sub, '*': mul, '/': lambda x, y: int(x / y)}
def evalRPN(self,tokens):
stack=[]
for s in tokens:
if s not in {'+','-','*','/'}:
stack.append(int(s))
else:
op2=stack.pop()
op1=stack.pop()
stack.append(self.op_map[s](op1,op2))
return stack.pop()
if __name__=="__main__":
tokens=input().strip().split()
solution=Solution()
n=solution.evalRPN(tokens)
print(n)
我想我是把输入输出想的太复杂了!如果想的简单一点就这样直接输出,然后去除一点空格就行了
注意除法的顺序就行了
三、239. 滑动窗口最大值
1、核心代码
from collections import deque
class MyQueue: #单调队列(从大到小
def __init__(self):
self.queue = deque() #这里需要使用deque实现单调队列,直接使用list会超时
#每次弹出的时候,比较当前要弹出的数值是否等于队列出口元素的数值,如果相等则弹出。
#同时pop之前判断队列当前是否为空。
def pop(self, value):
if self.queue and value == self.queue[0]:
self.queue.popleft()#list.pop()时间复杂度为O(n),这里需要使用collections.deque()
#如果push的数值大于入口元素的数值,那么就将队列后端的数值弹出,直到push的数值小于等于队列入口元素的数值为止。
#这样就保持了队列里的数值是单调从大到小的了。
def push(self, value):
while self.queue and value > self.queue[-1]:
self.queue.pop()
self.queue.append(value)
#查询当前队列里的最大值 直接返回队列前端也就是front就可以了。
def front(self):
return self.queue[0]
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
que = MyQueue()
result = []
for i in range(k): #先将前k的元素放进队列
que.push(nums[i])
result.append(que.front()) #result 记录前k的元素的最大值
for i in range(k, len(nums)):
que.pop(nums[i - k]) #滑动窗口移除最前面元素
que.push(nums[i]) #滑动窗口前加入最后面的元素
result.append(que.front()) #记录对应的最大值
return result
刷到目前最长的python代码出现了!
右进左出
Python的collections.deque为了保持与列表的一致性和简化学习曲线,采用了append来向队尾添加元素和appendleft来向队首添加元素的方法名称。同样地,pop方法用于从队尾移除元素,而popleft用于从队首移除元素。
进口是后端pop,queue[-1],出口是前端queue[0] popleft
这道题不是很熟
2、输入输出
from collections import deque
class MyQueue:
def __init__(self):
self.queue=deque()
def pop(self,num):
if self.queue and num==self.queue[0]:
self.queue.popleft()
def push(self,num):
while self.queue and num>self.queue[-1]:
self.queue.pop()
self.queue.append(num)
def front(self):
return self.queue[0]
class Solution:
def maxSlidingWindow(self,nums,k):
que=MyQueue()
result=[]
n=len(nums)
for i in range(k):
que.push(nums[i])
result.append(que.front())
for i in range(k,n):
que.pop(nums[i-k])
que.push(nums[i])
result.append(que.front())
return result
if __name__=="__main__":
nums=list(map(int,input().strip().split(',')))
k=int(input())
solution=Solution()
result=solution.maxSlidingWindow(nums,k)
print(result)
总结
输入输出