1.栈和队列
![](https://i-blog.csdnimg.cn/blog_migrate/c4962d6284a8fd6ece8319897d36f87d.png)
在python里面,栈和列表都可以用列表来模拟,都可以用append和pop
栈 入是append() 出是pop()
列表入是append() 出是pop(0)
2.栈的经典题型
232. 用栈实现队列 - 力扣(LeetCode) (leetcode-cn.com)
这个题还蛮有意思,用两个栈来实现队列的功能。
class MyQueue:
def __init__(self):
self.stackIn= []
self.stackOut=[]
def push(self, x: int) -> None:
#push 直接往in里面放
self.stackIn.append(x)
def pop(self) -> int:
#pop应该从out取 ,但是要判断pop是否存在 如果不存在就要将in 全部取出来
if not self.stackOut:
while self.stackIn:
self.stackOut.append(self.stackIn.pop())
return self.stackOut.pop()
def peek(self) -> int:
ls = self.pop() #将第一个弹出来 ,然后再放回out里面
self.stackOut.append(ls)
return ls
def empty(self) -> bool:
return not self.stackOut and not self.stackIn #都为空 才为true
# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()
20. 有效的括号 - 力扣(LeetCode) (leetcode-cn.com)
class Solution:
def isValid(self, s: str) -> bool:
#先入后出 用栈
stacker=[]
for i in s:
if i =='(': stacker.append(')')
elif i=='[':stacker.append(']')
elif i== '{':stacker.append('}')
elif not stacker or i!= stacker.pop():return False
return False if stacker else True
1047. 删除字符串中的所有相邻重复项 - 力扣(LeetCode) (leetcode-cn.com)
class Solution:
def removeDuplicates(self, s: str) -> str:
#栈操作
stacker= []
for i in s:
if not stacker or stacker[-1]!= i: stacker.append(i)
else: stacker.pop()
return ''.join(stacker)
150. 逆波兰表达式求值 - 力扣(LeetCode) (leetcode-cn.com)
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
#栈
#遇见+-*/ 要取值 第一次取两个 后面每次取一个
#if len(tokens) ==1:return int(tokens[-1])
stacker= []
comsign='+-*/'
for i in tokens:
if i not in comsign:
stacker.append(i)
else:
pop2, pop1= stacker.pop(), stacker.pop() #取两个
coms= int(eval(pop1+i+pop2))
stacker.append(str(coms))
return int(stacker.pop())
3.队列的经典题型
225. 用队列实现栈 - 力扣(LeetCode) (leetcode-cn.com)
题目要求是用两个队列实现栈,不过一个队列就可以实现
class MyStack:
#用两个队列来实现栈 另外一个队列用来存储 读取顶部完毕再全部放回第一个队列
#用一个队列来实现,每次读头都都要把其他放到尾巴上
def __init__(self):
self.que1 =[]
def push(self, x: int) -> None:
self.que1.append(x)
def pop(self) -> int:
n = len(self.que1)
for i in range(n-1):
self.que1.append(self.que1.pop(0))
return self.que1.pop(0)
def top(self) -> int:
res= self.pop()
self.que1.append(res)
return res
def empty(self) -> bool:
return not self.que1
# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()
239. 滑动窗口最大值 - 力扣(LeetCode) (leetcode-cn.com)
这道题用到单调队列,还是挺难的,这道题。
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
#首先用的是单调递减队列
#遵循2个规律
#1.如果移除元素等于出口元素,弹出元素,其余时间不做处理
#2.如果push元素值大于队列末尾元素,将末尾元素弹出,直到小于等于末尾元素,保证队列保证单调递减
quer,res=[],[]
for i in range(len(nums)):
#入i 出i-k
if i >=k and nums[i-k]== quer[0]: quer.pop(0) #出i-k
while quer and quer[-1]<nums[i]: quer.pop() #入 #队列保持单调递减
quer.append(nums[i])
res.append(quer[0])
return res[k-1::]
347. 前 K 个高频元素 - 力扣(LeetCode) (leetcode-cn.com)
堆? 小顶堆 ?大顶堆?要学习下
堆包含大小顶堆 是完全二叉树
大顶堆是父节点大于等于孩子节点
小顶堆是父节点小于等于孩子节点
因为查找时间需要logn,可以快速操作,减少时间
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
#用map保存频率
import heapq
maper={}
for i in nums: maper[i]= maper.get(i,0)+1 #找不到返回0
res=[]
#产生k大小的小顶堆
for keyer, val in maper.items():
heapq.heappush(res,(val, keyer))
if len(res)>k:heapq.heappop(res)
return [_[1] for _ in res] #将keyer 输出
4.总结
可以用栈和队列操作的都比较固定,倒是最后的大小顶栈,让我收获颇多。