文章链接:代码随想录
232. 用栈实现队列 + 225. 用队列实现栈 + 20. 有效的括号 + 1047.删除字符串中的所有相邻重复项
视频链接:栈的基本操作! | LeetCode:232.用栈实现队列_哔哩哔哩_bilibili
继续补作业,开始学习栈和队列的内容。
232.用栈实现队列
状态:看视频,再自己复现代码
思路:用stackin 和 stackout两个栈来实现队列,比较复杂的操作是移除首部元素pop()函数:要将stackin进栈数据全部导入到stackout,再从stackout弹出数据
总结:
1. python中用的是list()来模拟栈,有pop(), append()等操作
2. 写peek()函数时可以复用pop(),但要注意将弹出的数据重新存入栈
3. 判断队列是否为空时,要同时检查stackin 和 stackout两个栈
4.
时间复杂度: push和empty为O(1), pop和peek为O(n)
空间复杂度: O(n)
class MyQueue:
def __init__(self):
self.stackin = []
self.stackout = []
def push(self, x: int) -> None:
self.stackin.append(x)
def pop(self) -> int:
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:
ans = self.pop()
self.stackout.append(ans)
return ans
def empty(self) -> bool:
return not (self.stackin or self.stackout)
# 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()
225. 用队列实现栈
状态:看视频,再自己复现代码
思路:用一个队列实现,移除栈顶元素pop()函数的实现:将队列头部的(size-1)个元素依次添加到队列尾部,再弹出最后一个元素
总结:
1. 用python库collections中的双向队列deque来模拟, 弹出数据用的是popleft()
2. 还有用两个队列来模拟栈的思路,其中一个队列用来存储数据,另一个队列只在pop()中用到,具体写法参考:
代码随想录
3. 类似上一题,写top()函数时可以复用pop(),但要注意将弹出的数据重新存入队列
4.
时间复杂度: push和empty为O(1), pop和top为O(n)
空间复杂度: O(n)
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) -> int:
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) -> int:
ans = self.pop()
self.que.append(ans)
return ans
def empty(self) -> bool:
return not self.que
# 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. 有效的括号
状态:看视频,再复现代码
思路&总结:
技巧:遍历字符串,遇到左括号时,就将对应的右括号存入栈;遍历至右括号时,比较当前元素是否等于栈顶元素
1. 不匹配的3种情况:
1)字符串里左方向的括号多余
2)括号没有多余,但是括号的类型不匹配
3)字符串里右方向的括号多余
针对以上3种不匹配情况,会出现的结果有:
1)已遍历完字符串,但栈不为空,因为有相应的左括号没有右括号来匹配,所以return false
2)在遍历过程中,发现栈里没有能匹配的字符,所以return false
3) 在遍历过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号,return false
2. 另一种解法使用栈和字典,用字典对括号对进行mapping,如key为 '(', 相应的value为 ')'。具体写法参考:代码随想录
3. 剪枝:当字符串中的元素为奇数个时,一定不匹配,可以直接return false
4.
取list的最后一个元素stack[-1],就是模拟取栈顶元素
5. 时间复杂度: O(n),空间复杂度: O(n)
class Solution:
def isValid(self, s: str) -> bool:
stack = []
if len(s) % 2 != 0:
return False
for i in range(len(s)):
if s[i] == '(':
stack.append(')')
elif s[i] == '[':
stack.append(']')
elif s[i] == '{':
stack.append('}')
elif not stack or s[i] != stack[-1]:
return False
else:
stack.pop()
return True if not stack else False
1047. 删除字符串中的所有相邻重复项
状态:有了上一题的基础,这道题很快有思路了,自己写代码AC
思路:初始化一个空栈,遍历字符串,将遍历过的元素依次存入栈,若当前元素等于栈顶元素,则弹出该栈顶元素,以此类推,直到遍历完成,最后栈内剩余的元素组合起来就是最终的字符串
总结:
1. 时间复杂度: O(n),空间复杂度: O(n)
class Solution:
def removeDuplicates(self, s: str) -> str:
a = []
for i in s:
if a and a[-1] == i:
a.pop()
else:
a.append(i)
return ''.join(a)