【CV炼丹师勇闯力扣训练营 Day10】

CV炼丹师勇闯力扣训练营

代码随想录算法训练营第10天
232.用栈实现队列
225.用队列实现栈
20.有效括号
1047删除字符串中的所有相邻重复项


一、232用栈实现队列

使用栈实现队列的下列操作:
push(x) – 将一个元素放入队列的尾部。
pop() – 从队列首部移除元素。
peek() – 返回队列首部的元素。
empty() – 返回队列是否为空。

【示例】
MyQueue queue = new MyQueue();
queue.push(1);
queue.push(2);
queue.push(3);
queue.peek(); // 返回 1
queue.pop(); // 返回 1
queue.empty(); // 返回 false

【思路】用一个输入栈,一个输出栈模拟队列
【注意】在push数据的时候,只要数据放进输入栈就好,但在pop的时候,操作就复杂一些,输出栈如果为空,就把进栈数据全部导入进来(注意是全部导入),再从出栈弹出数据,如果输出栈不为空,则直接从出栈弹出数据就可以了。最后如何判断队列为空呢?如果进栈和出栈都为空的话,说明模拟的队列为空了。

1

代码如下(Python):

class MyQueue:
    def __init__(self):
        self.stack_in = []  # 进栈
        self.stack_out = []  # 出栈

    def push(self, x: int) -> None:
        self.stack_in.append(x)

    def pop(self) -> int:
        if self.empty():  # 先判断进栈和出栈是否都为空
            return None

        if self.stack_out:  # 判断出栈是否不为空,若不为空,直接pop
            return self.stack_out.pop()
        else:
            for i in range(len(self.stack_in)):  # 若进栈不空,出栈为空,则先进栈pop填充出栈,再出栈pop
                self.stack_out.append(self.stack_in.pop())  # stack_out: [3,2,1]
            return self.stack_out.pop()  # 弹出1 stack_out: [3,2]

    def peek(self) -> int:
        # 返回队列前端的元素(即下一次要弹出的元素),而不对队列进行任何修改
        ans = self.pop()
        self.stack_out.append(ans)  # 将弹出的1补回去, stack_out: [3,2,1]
        return ans  # 1

    def empty(self) -> bool:
        # 判断队列是否为空
        return not (self.stack_in or self.stack_out)

MQ = MyQueue()
MQ.push(1)
MQ.push(2)
MQ.push(3)
print(MQ.stack_in)  # [1,2,3]
print(MQ.peek())  # 1
print(MQ.stack_out)  # [3,2,1]

二、 225用队列实现栈

使用队列实现栈的下列操作:

push(x) – 元素 x 入栈
pop() – 移除栈顶元素
top() – 获取栈顶元素
empty() – 返回栈是否为空

【思路1】用两个队列模拟栈,只不过这两个栈不是分别用于进出,第二个栈只用于备份
【思路2】用一个队列模拟栈

快慢指针动图

代码如下(Python):

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):  # [3,2,1] -> [2,1,3]
            self.que.append(self.que.popleft())
        print(self.que)  # deque([3, 1, 2])
        return self.que.popleft()  # 弹出3

    def top(self) -> int:
        # 写法一:
        # if self.empty():
        #     return None
        # return self.que[-1]

        # 写法二:
        if self.empty():
            return None
        for i in range(len(self.que)-1):
            self.que.append(self.que.popleft())
        temp = self.que.popleft()
        self.que.append(temp)
        return temp

    def empty(self) -> bool:
        return not self.que


# Your MyStack object will be instantiated and called as such:
obj = MyStack()
obj.push(1)
obj.push(2)
obj.push(3)
print(obj.que)  # deque([1, 2, 3])
param_2 = obj.pop()
print(obj.que)  # deque([1, 2])
param_3 = obj.top()  # 2
param_4 = obj.empty()

三、20有效的括号

给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。

示例 1:
输入:s = “()”
输出:true

示例 2:
输入:s = “()[]{}”
输出:true

示例 3:
输入:s = “(]”
输出:false

由于栈结构的特殊性,非常适合做对称匹配类的题目。
【不匹配的情况】
①字符串里左方向的括号多余了,所以不匹配
②括号没有多余,但是括号的类型没有匹配上
③字符串里右方向的括号多余了,所以不匹配
【思路】字符串遍历完之后,栈是空的,就说明全都匹配了
1

代码如下(Python):

class Solution:
    def isValid(self, s: str) -> bool:
        stack = []  # 栈中用于存放遍历到的左括号

        for item in s:
            if item == '(':
                stack.append(')')
            elif item == '[':
                stack.append(']')
            elif item == '{':
                stack.append('}')
            elif not stack or stack[-1] != item:  # 【注意】得先判断栈是否为空,再对栈的最后一个元素做判断
                return False  # ①item没空,stack空了:右边多了 ②不匹配
            else:
                stack.pop()  # 匹配

        return True if not stack else False  # ③item空了,stack没空:左边多了
        

四、1047删除字符串中的所有相邻重复项

给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
S 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

示例:
输入:“abbaca”
输出:“ca”

解释:
例如,在 “abbaca” 中,我们可以删除 “bb” 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 “aaca”,其中又只有 “aa” 可以执行重复项删除操作,所以最后的字符串为 “ca”。

【思路】匹配相邻元素,本质也是消消乐,用栈来解决。栈中存放遍历过的元素,当遍历当前的这个元素的时候,去栈里看一下我们是不是遍历过相同数值的相邻元素,然后再去做对应的消除操作


从栈中弹出剩余元素,此时是字符串ac,因为从栈里弹出的元素是倒序的,所以再对字符串进行反转一下,就得到了最终的结果。

代码如下(Python):

# 方法一,使用栈
class Solution:
    def removeDuplicates(self, s: str) -> str:
        res = list()
        for item in s:
            if res and res[-1] == item:  # 栈不为空且匹配则弹出栈
                res.pop()
            else:
                res.append(item)  # 否则入栈
        # ['c', 'a'] -> ca
        return "".join(res)  # 字符串列表拼接


# 方法二,使用双指针模拟栈,如果不让用栈可以作为备选方法。
class Solution1:
    def removeDuplicates(self, s: str) -> str:
        res = list(s)
        slow = fast = 0
        length = len(res)

        while fast < length:
            # 如果一样直接换,不一样会把后面的填在slow的位置
            res[slow] = res[fast]

            # 如果发现和前一个一样,就退一格指针
            if slow > 0 and res[slow] == res[slow - 1]:
                slow -= 1
            else:
                slow += 1
            fast += 1

        return ''.join(res[0: slow])

S = Solution()
print(S.removeDuplicates("abbaca"))

  • 12
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值