LeetCode 232.用栈实现队列:
思路:
用两个独立的栈 in 和 out 实现队列,入队列操作只需要入栈即可;出队操作,若out非空,出栈out的元素,否则将 in 的元素全部出栈到 out 中再出栈元素。
使用了两个列表模拟两个栈,其中peek操作复用了pop操作
class MyQueue(object):
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 not self.stack_out:
while self.stack_in:
self.stack_out.append(self.stack_in.pop())
return self.stack_out.pop()
def peek(self):
"""
:rtype: int
"""
if self.empty():
return None
result = self.pop()
self.stack_out.append(result)
return result
def empty(self):
"""
:rtype: bool
"""
if self.stack_in or self.stack_out:
return False
return True
感悟:
使用栈模拟队列
python中使用列表来模拟栈
LeetCode 225.用队列实现栈:
思路:
- 用两个队列实现栈
① 使用“用栈实现队列”中的思路实现不了这道题的,因为元素在第一个队列中是前面,队列为先进先出,从而在第二个队列中还是前面,也就是说,元素从第一个队列转移到第二个队列中并没有发生变化。
② 实现的思路为:使用第二个队列作为备份。pop()函数的实现思路如下
③ 可以使用 list 或者 deque (双端队列)来模拟队列,但是使用 list.pop(0)的时间复杂度为O(n),从而实现的栈的pop()和top()的时间复杂度为O(n^2),因此采用deque实现。仅使用append()和popleft()作为进队和出队操作
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
# 将queue1中除最后一个元素外导入queue2
for i in range(len(self.queue1) - 1):
self.queue2.append(self.queue1.popleft())
# 交换queue1和queue2
self.queue1, self.queue2 = self.queue2, self.queue1
return self.queue2.popleft()
def top(self):
"""
:rtype: int
"""
"""
写法1:
元素只存在queue1中,dequeue可以实现索引访问
因此直接返回queue1[-1]
写法2:
类似pop()函数
先出队queue1的元素到queue2中,
queue1剩下一个元素,即要得到的元素
将queue1中最后一个元素出队到queue2中,再交换queue1和queue2
写法3:
对pop()的复用,
因为top()得到的栈顶元素是最后入栈的元素,且元素只存在queue1中,
因此result = pop()得到栈顶元素,再将result入队到queue1中
"""
if self.empty():
return None
# 写法1
#return self.queue1[-1] # 实际上用到了栈
# 写法2
for i in range(len(self.queue1) - 1):
self.queue2.append(self.queue1.popleft())
result = self.queue1.popleft()
self.queue1, self.queue2 = self.queue2, self.queue1
self.queue1.append(result)
return result
"""
# 写法3
result = self.pop()
self.queue1.append(result)
return result
"""
def empty(self):
"""
:rtype: bool
"""
if self.queue1:
return False
return True
- 使用一个队列模拟栈
使用两个队列模拟栈的思路进行迁移,只是移动除最后一个元素外的其它元素到备份队列变为移动到本队列队尾。
也就是将除最后一个元素外的其它元素出队并重新入队
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 i 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
# 写法1
#return self.queue[-1]
"""
# 写法2
for i in range(len(self.queue) - 1):
self.queue.append(self.queue.popleft())
result = self.queue.popleft() # 此时出队的为模拟栈的栈顶元素
self.queue.append(result)
return result
"""
# 写法3
result = self.pop()
self.queue.append(result)
return result
def empty(self):
"""
:rtype: bool
"""
if self.queue:
return False
return True
感悟:
学习思路不能简单迁移
LeetCode 20. 有效的括号:
思路:
括号不匹配有如下三种情况:
1)左括号缺少匹配的右括号:{ ( [ ] )
2) 右括号缺少匹配的左括号:( [ ] ) }
3) 对应的左右括号不匹配: { ( [ ] ) )
典型的使用栈的题目:遇到左括号入栈,遇到右括号出栈元素(tip:遇到左括号入栈对应的右括号,那么出栈时直接判断是否相等即可)
1)对应字符串判断完成后栈非空
2)对应字符串判断过程中栈空
3)对应字符串判断过程中栈顶元素不匹配
class Solution(object):
def isValid(self, s):
"""
:type s: str
:rtype: bool
"""
len_s = len(s)
if len_s % 2: # 奇数一定不匹配
return False
stack = []
for i in range(len_s):
if s[i] == '{':
stack.append('}')
elif s[i] == '[':
stack.append(']')
elif s[i] == '(':
stack.append(')')
else:
# 对应2)右括号没有匹配的左括号 3)左右括号不匹配
if not stack or s[i] != stack[-1]:
return False
stack.pop()
# 对应1) 左括号没有匹配的右括号
if stack:
return False
return True
感悟:
入栈左括号对应的右括号很好用
LeetCode 1047.删除字符串中的所有相邻重复项:
思路:
使用栈来实现。题目中需要选择两个相邻且相同的字母进行删除,且删除重复项后,重新拼在一起的字符串中有重复项需要继续删除。
- 直接使用栈来实现
class Solution(object):
def removeDuplicates(self, s):
"""
:type s: str
:rtype: str
"""
result = []
for si in s:
if not result or si != result[-1]:
result.append(si)
else:
result.pop()
return ''.join(result)
- 不能使用栈时,使用指针来模拟栈
class Solution(object):
def removeDuplicates(self, s):
"""
:type s: str
:rtype: str
"""
slow = -1 # 栈顶指针
result = list(s)
for i in range(len(s)):
# print('i: ' + str(s[i]))
# print('slow: ' + str(slow))
if slow == -1 or result[slow] != s[i]:
slow += 1
result[slow] = s[i]
# print(str(slow) + ' push ' + str(result[slow]))
else:
# print('pop ' + str(result[slow]))
slow -= 1
return ''.join(result[:slow + 1])
学习收获:
栈和队列的互相实现以及使用栈来完成各种任务