栈与队列:
-
栈提供push 和 pop 等等接口,所有元素必须符合先进后出规则,所以栈不提供走访功能,也不提供迭代器(iterator)。 不像是set 或者map 提供迭代器iterator来遍历所有元素。
-
栈的底层实现可以是vector,deque,list 都是可以的, 主要就是数组和链表的底层实现。

-
队列中先进先出的数据结构,同样不允许有遍历行为,不提供迭代器。
232.用栈实现队列
-
问题:(逻辑思路都了解,上手写就全是问题)
-
Q1: 在写constructor时,有些混乱。自己的写法是用#1 constructor
-
class MyQueue(object): # #1 def __init__(self, stack1=[], stack2=[]): self.stack_in = stack1 self.stack_out = stack2 #2 # def __init__(self): # self.stack_in = [] # self.stack_out = [] def push(self, x): """ :type x: int :rtype: None """ self.stack_in.append(x) def pop(self): """ :rtype: int """ if self.empty(): return None if len(self.stack_out) != 0: return self.stack_out.pop() else: for _ in range(len(self.stack_in)): self.stack_out.append(self.stack_in.pop()) return self.stack_out.pop() def peek(self): """ :rtype: int """ ans = self.pop() self.stack_out.append(ans) return ans def empty(self): """ :rtype: bool """ print('stack_in:',self.stack_in) print('stack_out:',self.stack_out) return len(self.stack_in) == 0 and len(self.stack_out) == 0 # 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() -
其余的都是对的,但是提交时报错如下

- 用这个用例来debug,结果给出如下结果

- 在群里提问得到解答如下:from 卡哥助手-坤坤
- “这个问题,和LeetCode的测试用例有关哈, 在初始化的时候,因为写构造函数是支持有参构造的,对于传入的stack_out不为空情况,按照展示的代码逻辑,如果传入的stack不为空,内部的定义的stack_out也会直接引用传入的非空栈,不会把传入的栈置空。所以导致,在初始化时,内部负责弹出元素的栈stack_out已经不为空了。”
- 如果想构造有参的构造函数,记得对传入的参数清空就行了
- 清空操作如下:
- 有参数和无参数构造函数的区别:
- 需要根据实际场景来分析,在领域驱动设计中,就会避免无参构造函数,这样在后续使用该实例的过程中,当执行一些逻辑时,不用重新给涉及到的属性进行赋值。
- Q2: 第一反应是由于有empty()函数,那么就定义变量 size。虽说不难理顺逻辑(push 就size++,pop就size--),但实际上len()对于stack的长度判断更加方便且是动态更改。
-
trick:对于pop():要判断stack_out是否为空,是因为stack_out的元素都是来自于stack_in,因此只要stack_out不为空,就说明当前队列的第一个或前几个元素都在stack_out里,这样pop()就是想要的结果;同时当stack_out不为空时,就不能向其加入新的元素,否则就会打乱顺序而出错。
-
对于if len(self.stack_out) != 0:的判断,另一种简易写法if self.stack_out:总是需要思考一下,不习惯这样写,需要多练习。默认情况下是false,对应这里就是不为空。
-
225. 用队列实现栈
-
第一反应是利用from collections import deque,deque是双向的。
-
from collections import deque
class MyStack(object):
def __init__(self):
self.queue1 = deque()
# self.queue2 = deque()
def push(self, x):
"""
:type x: int
:rtype: None
"""
self.queue1.append(x)
def pop(self):
"""
:rtype: int
"""
return self.queue1.pop()
def top(self):
"""
:rtype: int
"""
ans = self.pop()
self.queue1.append(ans)
return ans
def empty(self):
"""
:rtype: bool
"""
return len(self.queue1) == 0
# 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()
-
这样做看似简单,但是是有问题的。在实现pop()时直接使用了 self.queue1.pop(),这实际上是直接用了栈的功能,队列的pop()取到的是不一样的!这里容易犯简单的错误
-
题解1:
- trick: 在把除了最后一个元素都放到另一个队列之后,要把这两个队列swap。这样做是保证只有队列1存储元素,同时写法相对简单,要不然还要把队列2的所有元素重新放回队列1中。
class MyStack(object):
def __init__(self):
self.queue1 = deque()
self.queue2 = deque()
def push(self, x):
"""
:type x: int
:rtype: None
"""
self.queue1.append(x)
def pop(self):
"""
:rtype: int
"""
if self.empty():
return None
for _ in range(len(self.queue1)-1):
self.queue2.append(self.queue1.popleft())
self.queue1, self.queue2 = self.queue2, self.queue1
return self.queue2.pop()
'''
def pop(self):
"""
:rtype: int
"""
if self.empty():
return None
for _ in range(len(self.queue1)-1):
self.queue2.append(self.queue1.popleft())
ans = self.queue1.popleft()
for _ in range(len(self.queue2)):
self.queue1.append(self.queue2.popleft())
return ans
'''
def top(self):
"""
:rtype: int
"""
if self.empty():
return None
return self.queue1[-1]
def empty(self):
"""
:rtype: bool
"""
return len(self.queue1) == 0
# 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()
-
也可用一个队列来实现
class MyStack(object):
def __init__(self):
self.queue = deque()
def push(self, x):
"""
:type x: int
:rtype: None
"""
self.queue.append(x)
def pop(self):
"""
:rtype: int
"""
if self.empty():
return None
for _ in range(len(self.queue)-1):
self.queue.append(self.queue.popleft())
return self.queue.popleft()
def top(self):
"""
:rtype: int
"""
if self.empty():
return None
return self.queue[-1]
def empty(self):
"""
:rtype: bool
"""
return len(self.queue) == 0
# 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()
-
20. 有效的括号
-
第一想法是用stack,但是写的时候没有考虑到continue来skip .append(char),否则就会出现找到了满足的情况但是还是将新的char加入到stack中。
-
题解:
-
class Solution(object):
def isValid(self, s):
"""
:type s: str
:rtype: bool
"""
stack = []
for char in s:
if len(stack)!=0:
if (char==')' and stack[-1]=='(') or (char==']' and stack[-1]=='[') or (char=='}' and stack[-1]=='{'):
stack.pop()
continue #once one of the above conditions satisfies, then .pop(), also need to skip .append()
stack.append(char)
print(stack)
return len(stack) == 0
-
1047. 删除字符串中的所有相邻重复项
-
这道题跟#20. 有效的括号实际上是一样的
-
题解:
-
class Solution(object):
def removeDuplicates(self, s):
"""
:type s: str
:rtype: str
"""
stack = []
for char in s:
if len(stack) != 0:
if stack[-1] == char:
stack.pop()
continue
stack.append(char)
return ''.join(stack)
总结:
-
栈与队列的题目相对简单,但是小的点也不少出错。当有思路时,尽量做到考虑周全,有些时候就是写的太快然后依赖运行结果来调试,这样虽说可以ac,但是并没有记住错误的原因。
-
用栈来实现队列和用队列实现栈需要再巩固一下
知识点:Stack implementation using lsit and collections.deque respectively
- Python’s built-in data structure list can be used as a stack. Instead of push(), append() is used to add elements to the top of the stack while pop() removes the element in LIFO order. Unfortunately, the list has a few shortcomings. The biggest issue is that it can run into speed issues as it grows. The items in the list are stored next to each other in memory, if the stack grows bigger than the block of memory that currently holds it, then Python needs to do some memory allocations. This can lead to some append() calls taking much longer than other ones.
- Python stack can be implemented using the deque class from the collections module. Deque is preferred over the list in the cases where we need quicker append and pop operations from both the ends of the container, as deque provides an O(1) time complexity for append and pop operations as compared to list which provides O(n) time complexity.


754




被折叠的 条评论
为什么被折叠?



