代码随想录算法训练营第十一天| LeetCode20. 有效的括号、LeetCode1047. 删除字符串中的所有相邻重复项 、LeetCode150. 逆波兰表达式求值

一、LeetCode20. 有效的括号

        1:题目描述(20. 有效的括号

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

        有效字符串需满足:

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

        2:解题思路

        有三种不匹配的情况:

        第一种:左括号没有匹配的右括号

        第二种:左括号和右括号没有按顺序进行匹配

         第三种:右括号多了,没有匹配的左括号

        我们只需要将这三种情况处理掉就可以了。

        下面描述的左括号为:(、{、[;右括号为:)、}、]

        在本题,我们使用栈来解题,定义一个栈stack,遍历字符串,当碰到左括号 时,向栈中添加对应的右括号;当遍历到右括号时,就去与栈顶的元素对比,看两者是否相等,为同一型号的右括号,如果不是同一型号的括号,则说明没有按顺序进行匹配(即第二种情况);如果此时栈已经为空了,说明多了右括号(即第三种情况);如果相等,我们就把栈顶的元素弹出,继续遍历下一个元素;当元素遍历完了后,如果栈stack不为空,说明多了左括号(即第一种情况);栈为空了,说明字符串满足条件。

class Solution:
    def isValid(self, s):
        # 定义一个栈
        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("]")
            # 当元素为右括号“)、}、]”时,去判断stack栈顶的元素是否为“)、}、]”
            # 如果不相等,说明闭合的顺序不正确
            # 如果栈已经为空了,说明没有与之匹配的左括号
            elif len(stack) == 0 or s[i] != stack[-1]:
                return False
            # 如果相等,则括号是匹配的,将栈顶的元素弹出,继续遍历下一个元素
            else:
                stack.pop()
        # 如果遍历完字符串,stack中还有元素,说明字符串中有左括号没有匹配的右括号
        if len(stack) != 0: return False
        # stack中没有元素了,说明括号都以正确的顺序进行闭合了
        return True

 可以将代码进行优化一下,我们可以将左括号对应的右括号存在一个字典中,遍历到左括号,就将左括号对应的右括号添加到栈stack中。

class Solution:
    def isValid(self, s):
        # 定义一个栈
        stack = []
        s_dict = {
            "(":")",
            "{":"}",
            "[":"]"
        }
        if len(s)%2 != 0: return False        # 当字符串的长度为奇数时,一定有不匹配的括号
        # 字符串的长度为偶数
        # 遍历字符串
        for i in range(len(s)):
            # 当元素为左括号时,向栈中添加对应的右括号
            if s[i] in s_dict:
                stack.append(s_dict[s[i]])
            # 当元素为右括号“)、}、]”时,去判断stack栈顶的元素是否为“)、}、]”
            # 如果不相等,说明闭合的顺序不正确
            # 如果栈已经为空了,说明没有与之匹配的左括号
            elif len(stack) == 0 or s[i] != stack[-1]:
                return False
            # 如果相等,则括号是匹配的,将栈顶的元素弹出,继续遍历下一个元素
            else:
                stack.pop()
        # 如果遍历完字符串,stack中还有元素,说明字符串中有左括号没有匹配的右括号
        if len(stack) != 0: return False
        return True

二、LeetCode1047. 删除字符串中的所有相邻重复项

        1:题目描述(1047. 删除字符串中的所有相邻重复项

        给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。

        在 S 上反复执行重复项删除操作,直到无法继续删除。

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

        2:解题思路

        使用栈来进行解题

        定义一个栈stack,来存放我们遍历字符串的的元素,当元素与栈顶元素相等时,将栈顶元素弹出,当栈为空或者元素与栈顶元素不相等时,将元素加入到栈中。

class Solution:
    def removeDuplicates(self, s):
        stack = []             # 定义一个栈,用来存放遍历过的元素
        for item in s:
            if len(stack) == 0:           # 当栈为空时,把元素加入到栈中
                stack.append(item)
            else:                         # 当栈不为空
                if item == stack[-1]:     # 当前元素与栈顶元素相等,则将栈顶元素弹出
                    stack.pop()
                else:                     # 当前元素与栈顶元素不相等,则将元素加入栈
                    stack.append(item)
        s = "".join(stack)                # 将栈中的元素拼接成字符串
        return s

 三、LeetCode150. 逆波兰表达式求值

        1:题目描述(150. 逆波兰表达式求值

        根据 逆波兰表示法,求表达式的值。

        有效的算符包括 +、-、*、/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

        注意 两个整数之间的除法只保留整数部分。

        可以保证给定的逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。

        2:解题思路

        先来看看什么是逆波兰表达式。

        逆波兰表达式:是一种后缀表达式,所谓后缀就是指算符写在后面。

        平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。

        该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。

        逆波兰表达式主要有以下两个优点:

  • 去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。

  • 适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中

        因此先定义一个栈stack,然后遍历tokens,如果遍历的元素是数字,则将数字加入到栈stack中,如果遍历的元素是“+、-、*、/”,则从栈顶依次取出两个元素,转换为int类型后分别赋值给nums1,nums2,然后对取出的两个元素按照遍历到的运算符进行运算,nums2+nums1,nums2-nums1,nums2*nums1,nums2/nums1;再将得到的运算结果添加到栈stack中,进入遍历下一个元素,直到遍历完tokens,此时stack中存放的是逆波兰表达式运算的结果,把stack中的元素弹出进行返回;当tokens只有一个元素时,stack中只有这一个元素,最后返回时,需要进行类型转换。

class Solution:
    def evalRPN(self, tokens):
        stack = []                 # 定义一个栈,用来存放遍历tokens的元素,及运算结果
        # 遍历tokens
        for item in tokens:
            # 当元素为“+、-、*、/”
            if item == "+" or item == "-" or item == "*" or item == "/":
                # 取出栈stack中的栈顶的两个元素,取出来的元素是字符串,需要进行转化
                nums2 = int(stack.pop())
                nums1 = int(stack.pop())
                # 元素为+时,进行加法运算,再将运算的结果添加到栈stack中
                if item == "+":
                    stack.append(nums1+nums2)
                # 元素为-时,进行减法运算,再将运算的结果添加到栈stack中
                elif item == "-":
                    stack.append(nums1-nums2)
                # 元素为*时,进行乘法运算,再将运算的结果添加到栈stack中
                elif item == "*":
                    stack.append(nums1*nums2)
                # 元素为/时,进行除法运算,再将运算的结果添加到栈stack中
                elif item == "/":
                    stack.append(nums1/nums2)
            # 当元素为数字时,将元素加入到栈中
            else:
                stack.append(item)
        # 遍历完tokens后,栈中存放的时逆波兰表达式的结果
        # 当tokens只有一个元素时,stack中只有这一个元素,最后返回时,需要进行类型转换
        res = int(stack.pop())
        return res

        使用eval()函数

class Solution:
    def evalRPN(self, tokens):
        stack = []                 # 定义一个栈,用来存放遍历tokens的元素,及运算结果
        tokens_set = {"+","-","*","/"}
        # 遍历tokens
        for item in tokens:
            # 当元素为“+、-、*、/”
            if item in tokens_set:
                first_nums = stack.pop()
                second_nums = stack.pop()
                # 将nums1与nums1运算的结果,再添加到stack中
                # 从栈stack中弹出的第一个元素,在运算符的后面
                stack.append(int(eval(f'{second_nums} {item} {first_nums}')))    
            # 当元素为数字时,将元素加入到栈中
            else:
                stack.append(item)
        # 遍历完tokens后,栈中存放的时逆波兰表达式的结果
        # 当tokens只有一个元素时,stack中只有这一个元素,最后返回时,需要进行类型转换
        res = int(stack.pop())
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值