代码随想录算法训练营第十天|leetcode232.用栈实现队列、leetcode225. 用队列实现栈、leetcode20. 有效的括号、leetcode1047. 删除字符串中的所有相邻重复项
1 leetcode232.用栈实现队列
题目链接:232. 用栈实现队列 - 力扣(LeetCode)
文章链接:代码随想录
视频链接:栈的基本操作! | LeetCode:232.用栈实现队列_哔哩哔哩_bilibili
自己的思路:真的第一次接触这个概念,完全没有任何思路,甚至不知道从何下手
1.1 基本概念
- 栈就是相当于砌墙的砖头,先进后出,先放进去的元素最后才能出来,有个底兜着
- 队列就好像我们排队去看展览一样,先进先出,先进去看完就先出来,去做别的事情
- 用栈实现队列,那么就是在开辟一个栈,将之前栈里的内容全部存储到新的栈里面,然后再进行输出,就实现了队列
1.2 视频后的操作
思路:
- 对元素推到末尾,对于栈而言就是入栈,所以直接在空列表中加入数据
- 队列开头元素移除并返回移除的元素
- 那么根据栈的知识,就是首先判断所构建的队列是不是空的,如果是空的就没办法移除,先判断完成
- 然后要判断出栈的列表有没有值,有值也无法完成操作
- 出栈列表为空以后,然后对出栈列表进行元素加进去,并对入栈的列表进行删除
- 返回出栈列表的第一个数
- 返回列表的开头数,就是先将出栈的头部数值拿出来,拿出来以后还需要将其放回出栈中,所以需要一个相当于存储的东西,最后返回存储的值
- 判断列表是不是空的,空的返回
true
,有值就返回false
那么就是先对其入栈列表和出栈列表求一下二者有没有值,有值会是true
,然后在进行not true
即可
class MyQueue:
def __init__(self):
self.stack_in = []
self.stack_out = []
def push(self, x: int) -> None:
return self.stack_in.append(x)
def pop(self) -> int:
if self.empty():
return None
if self.stack_out:
return self.stack_out.pop()
else:
for i in range(len(self.stack_in)):
self.stack_out.append(self.stack_in.pop())
return self.stack_out.pop()
def peek(self) -> int:
ans = self.pop()
self.stack_out.append(ans)
return ans
def empty(self) -> bool:
return not(self.stack_in or self.stack_out)
# 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()
1.3 本题小结
- 出入这种题,才开始被这个概念吓到了,其实仔细一看,就是列表的一种创建方式吧,对于python语言来说,对于其他语言可能有更多不同的方法吧
- 这道题学会了一种类别函数里面的函数之间的调用方法,挺强大的,感觉自己以后也可以这么写代码,之前的代码真的写的不是很行
2 leetcode225. 用队列实现栈
题目链接:225. 用队列实现栈 - 力扣(LeetCode)
文章链接:代码随想录
视频链接:队列的基本操作! | LeetCode:225. 用队列实现栈_哔哩哔哩_bilibili
自己的思路:根据前一道题的思路,想着再建立一个队列,然后对其进行放数值
2.1 看视频后的思路
2.1.1 两个队列的方法
思路:
- 建立一个
deque
的数据形式,然后使用里面的append
是添加元素,以及popleft
来移除元素 - 其他的其实思路和栈的相似
from collections import deque
class MyStack:
def __init__(self):
self.queue_in = deque()
self.queue_out = deque()
def push(self, x: int) -> None:
return self.queue_in.append(x)
def pop(self) -> int:
if self.empty():
return None
for i in range(len(self.queue_in)-1):
self.queue_out.append(self.queue_in.popleft())
self.queue_in,self.queue_out = self.queue_out,self.queue_in
return self.queue_out.popleft()
def top(self) -> int:
if self.empty():
return None
tmp = self.pop()
self.queue_in.append(tmp)
return tmp
def empty(self) -> bool:
return len(self.queue_in)==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()
2.1.2 用一个列表实现的方法
思路:
这个思路超级简单,就是将移除的元素往后添加就好啦
from collections import deque
class MyStack:
def __init__(self):
self.queue = deque()
def push(self, x: int) -> None:
return self.queue.append(x)
def pop(self) -> 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) -> int:
tmp = self.pop()
self.queue.append(tmp)
return tmp
def empty(self) -> 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()
2.2 本题小结
- 关于python中的调用
deque
的代码from collections import deque
,这是一个双端队列的数据结构类型 - 其实发现这种题比链表简单,自己觉得难的时候是因为自己不想去尝试
3 leetcode20. 有效的括号
题目链接:225. 用队列实现栈 - 力扣(LeetCode)
文章链接:代码随想录
视频链接:队列的基本操作! | LeetCode:225. 用队列实现栈_哔哩哔哩_bilibili
自己的思路:才开始的思路就是找到几个括号,找到了就返回True
,否则就返回False
3.1 自己的代码
这个代码在所给的几个示例中是完全可以用的,但是在提交的时候,遇到了s ="(){}}{"
示例的时候就报错了
class Solution:
def isValid(self, s: str) -> bool:
if ('()'in s) or ('[]' in s) or ('{}' in s):
return True
return False
看完视频以后我感觉我的思路上去就是错的,不过尝试了也就知道自己做这种题的不妥之处了
3.2 视频后的思路
3.2.1 使用栈
思路:
- 首先会出现的不对的类型进行划分,第一种是有左没右,第二种是括号匹配不上,第三种是右括号多余了
- 然后就是对题目的思考,首先如果这个括号是奇数,就一定不满足条件可以返回
- 然后就可以对括号进行存储,如果遇到左括号就存储右括号,这样的遇到了右括号出栈就会方便许多
- 但是对栈而言,更需要保证这个出栈的栈不为空,如果是空的就没有出的
- 循环结束后,如果栈为空,就是
True
,否则也是false
class Solution:
def isValid(self, s: str) -> bool:
l_s = list()
if len(s)%2 !=0:
return False
for i in range(len(s)):
if s[i] == '(':
l_s.append(')')
elif s[i] == '[':
l_s.append(']')
elif s[i] == '{':
l_s.append('}')
elif l_s == [] or s[i] !=l_s[-1]:
return False
else:
l_s.pop()
return l_s == []
3.2.2 使用字典的方法
其实思路和栈的差不多,只是将栈的中间的存储数据的方式改了一下,这样好像运行变快了
class Solution:
def isValid(self, s: str) -> bool:
stack = list()
mapping = {'(':')','[':']','{':'}'}
if len(s)%2 !=0:
return False
for i in s:
if i in mapping.keys():
stack.append(mapping[i])
elif stack == [] or i !=stack[-1]:
return False
else:
stack.pop()
return stack == []
3.3 本题小结
- 这一道题主要就是思考的时候会有一些小问题,才开始没有想到这种题的一个思路,其次是对栈理解真的不够深,第一次接触就会有很多地方出问题
- 这道题让我更加深刻的理解了列表中的
append
和pop
函数,append函数在内部增加元素的时候,就是在最后面插入元素,pop删除元素也是同样的道理 - 还是会在if条件判断的时候将双等号写成单等号,希望以后少犯错误
4 leetcode1047. 删除字符串中的所有相邻重复项
题目链接:1047. 删除字符串中的所有相邻重复项 - 力扣(LeetCode)
文章链接:代码随想录
视频链接:栈的好戏还要继续!| LeetCode:1047. 删除字符串中的所有相邻重复项_哔哩哔哩_bilibili
自己的思路:第一眼看上去我觉得和上一道题的思路非常像,但是下手的时候才开始没有办法,但是因为用python语言麻,实现的时候是列表存储,后面就想着其实顺序和那个本身顺序是一样的,直接加一个join
函数就行了
4.1 自己的代码
class Solution:
def removeDuplicates(self, s: str) -> str:
stack = []
for i in s:
if stack == [] or stack[-1]!= i:
stack.append(i)
else:
stack.pop()
return ''.join(stack)
4.2 看视频后的思路
这道题能想出双指针的方法,真的他们超聪明,我只能说理解了,但是自己写的话还是很有问题,自己用笔画了一遍写的,不是那么的熟练
class Solution:
def removeDuplicates(self, s: str) -> str:
stack = list(s)
fast = slow = 0
length = len(stack)
while fast<length:
stack[slow] = stack[fast]
if slow>0 and stack[slow]==stack[slow-1]:
slow-=1
else:
slow +=1
fast +=1
return ''.join(stack[0:slow])
4.3 本题小结
- 这道题真的可以说是上一题的扩展,思路挺简单的,我也学会啦
- 但是这道题双指针的方法也真的厉害的,不过如果直接看是有些迷惑的,但是练习以后就会好很多
5 今日小结
- 掌握的栈和队列,栈是先进后出,队列是先进先出
- 对于python而言使用列表即可模仿栈,对于队列的模仿,需要从
collections
库中调用deque
,然后进行操作 - 对于第三题,主要是思路上的问题,需要掌握这种思路,分析问题的能力很重要吧