代码随想录算法训练营第11天|● 20. 有效的括号 ● 1047. 删除字符串中的所有相邻重复项 ● 150. 逆波兰表达式求值


前言


教程链接

💛栈这种结构非常适合做相邻字符的操作,包括消除、匹配、计算等

20. 有效的括号

在这里插入图片描述

三种不匹配的情况
在这里插入图片描述

思路

第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false

第二种情况:遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false

第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false
总体思路:如果是true的情况, 中间遍历的过程中一定有一个是与stack的top元素匹配 【到了对称的地方了】, 那么这个匹配的就可以pop出去,且紧跟着后面的应该也是匹配的;

压栈进去的是左边括号

💖小技巧: 压栈进去的是左边的括号,但是存的时候使用右边括号,这样后续判断快一些。

剪枝:如果是奇数大小的话,那一定不匹配
在这里插入图片描述
时间复杂度: O(n)
空间复杂度: O(n)

方法一 只使用栈

自己写的注意点

  1. elif not stack or ele != stack[-1]:#注意两个条件的顺序不能颠倒
  2. 再记一下:注意python判断为空的语句是not stack
class Solution(object):
    def isValid(self, s):
        """
        :type s: str
        :rtype: bool
        """
        stack = []
        n = len(s)
        for ele in s:
            if ele == "(":
                stack.append(")")
            elif ele == "[":
                stack.append("]")
            elif ele == "{":
                stack.append("}")
            #三种情况排除之后下面就是右括号的情况
            elif not stack or ele != stack[-1]:#注意两个条件的顺序不能颠倒 
                return False
            elif ele == stack[-1]:# 直接写else也行
                stack.pop()
        if stack:
            return False
        else: return True

方法二 使用字典,思想一样

就是字典不用自己写前面三个if了

# 方法二,使用字典
class Solution:
    def isValid(self, s: str) -> bool:
        stack = []
        mapping = {
            '(': ')',
            '[': ']',
            '{': '}'
        }
        for item in s:
            if item in mapping.keys():
                stack.append(mapping[item])
            elif not stack or stack[-1] != item: 
                return False
            else: 
                stack.pop()
        return True if not stack else Fals

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

在这里插入图片描述

思路

总体思路:跟上个题目一样,使用结构就非常简单;如果栈为空或者top和当前字符不一样,就压栈,如果相同就pop;

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

方法一 使用栈

自己写的 非常简单

class Solution(object):
    # from collections import deque
    def removeDuplicates(self, s):
        """
        :type s: str
        :rtype: str
        """
        result = []
        for ele in s:
            if not result or ele != result[-1]:
                result.append(ele)
            else:
                result.pop()
        return "".join(result)

方法二 使用双指针

使用双指针模拟栈,如果不让用栈可以作为备选方法。

# 方法二,使用双指针模拟栈,如果不让用栈可以作为备选方法。
class Solution:
    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])

150. 逆波兰表达式求值

在这里插入图片描述

题外话

中缀表达式需要判断优先级,但是逆波兰表达式这样后缀表达式就是计算机友好的。
在这里插入图片描述

思路

这个之前python数据结构课程里面学过,所以理解的很快,也很简单
💖总体思路:使用栈,遇到数字压栈,遇到运算符就弹出两个数字将计算结果压栈
在这里插入图片描述

方法一

写代码小细节

  1. 判断是否为运算符,可以在+、-、*、/里面先比较,如果不是就是数字啦
  2. 💘第一个出来的在运算符后面【非常重要】
  3. 可以用eval:eval(f’{second_num} {item} {first_num}’ – 执行字符串
    • f表示string,{}是占位符
  4. 也可以使用operator,但是没有/,使用lambda x, y : int(x/y)

下面自己写的代码:pycharm运行没错,力扣判错,,麻了

class Solution(object):
    def evalRPN(self, tokens):
        """
        :type tokens: List[str]
        :rtype: int
        """
        stack = []
        for  ele in tokens:
            if ele not in ["+","-","*","/"]:
                stack.append(ele)
            else:#不是数字的情况
                num2 = stack.pop()
                num1 = stack.pop()
                if ele == "+":
                    stack.append(int(num1)+int(num2))
                elif ele == "-":
                    stack.append(int(num1)-int(num2))
                elif ele == "*":
                    stack.append(int(num1)*int(num2))
                else:
                    stack.append(int(num1)/int(num2))
        return stack.pop()

方法二 python用operator或者eval呀~

from operator import add, sub, mul

class Solution:
    op_map = {'+': add, '-': sub, '*': mul, '/': lambda x, y: int(x / y)}
    
    def evalRPN(self, tokens: List[str]) -> int:
        stack = []
        for token in tokens:
            if token not in {'+', '-', '*', '/'}:
                stack.append(int(token))
            else:
                op2 = stack.pop()
                op1 = stack.pop()
                stack.append(self.op_map[token](op1, op2))  # 第一个出来的在运算符后面
        return stack.pop()

或者使用eval

class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        stack = []
        for item in tokens:
            if item not in {"+", "-", "*", "/"}:
                stack.append(item)
            else:
                first_num, second_num = stack.pop(), stack.pop()
                stack.append(
                    int(eval(f'{second_num} {item} {first_num}'))   # 第一个出来的在运算符后面
                )
        return int(stack.pop()) # 如果一开始只有一个数,那么会是字符串形式的

总结

今天这个也是很简单,多到时间把数据结构的二叉树学完;

  • 28
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第二十二算法训练营主要涵盖了Leetcode题目的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组找到长度最小的子数组,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值