leetcode刷题-栈与队列02

代码随想录栈与队列part02|20.有效的括号、1047. 删除字符串中的所有相邻重复项、150. 逆波兰表达式求值

20.有效的括号

leetcode题目链接
代码随想录文档讲解

思路
用栈解决的经典题目;
不匹配的场景就三个:

  1. 左边括号多余:({}
  2. 括号类型不匹配:[{(}}]、[{]}
  3. 右边括号多余:{})))

遇到左括号,把右括号加入栈;
遇到右括号,弹出栈中的元素,比较两个右括号是否一样
【若不匹配,说明字符串无效,情况2】
【若字符串还没遍历完,栈为空,说明字符串无效,情况3】
遍历完后,如果栈中还存有元素(栈不为空)【说明不匹配,字符串无效,情况1】

剪枝策略:
本题存在的一种情况:若字符串匹配,字符串长度一定是偶数
如果字符串是奇数的话,一定存在不匹配的括号

伪代码c++
注意: 判断时是top,之后是pop

stack<char>  st;
if(s.size%2 != 0) return false
for(int i=0; i<s.size(); i++){
	if(s[i]=='(')  st.push(')')
	else if(s[i]=='{') st.push('}')
	else if(s[i]=='[]) st.push(']')
	else if(! st.empty() && st.top() != s[i])
		return false;
	else st.pop()
}
return st.empty();  //处理第一种情况

python代码

# 第一次的实现代码
class Solution:
    def isValid(self, s: str) -> bool:
        dic = {'(':')', '[':']', '{': '}', '?':'?'}
        stack = ['?']
        for c in s:
            if c in dic: stack.append(c)
            elif dic[stack.pop()] != c: return False
        return len(stack) == 1
# 代码随想录代码
class Solution:
    def isValid(self, s: str) -> bool:
        if len(s) % 2 != 0:
            return False
        stack = []
        for c in s:
            if c == '(':
                stack.append(')')
            elif c == '{':
                stack.append('}')
            elif c == '[':
                stack.append(']')
            elif not stack or stack[-1] != c:
                return False
            else:
                stack.pop()
        return True if not stack else False
# 方法二,使用字典
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 False

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

leetcode题目链接
代码随想录文档讲解

思路

该题很多人可能不会想到用来解决,该题难点在于删除完目前存在的重复项之后可能会出现新的重复项,类似消消乐游戏。
请添加图片描述
没有必要真的用一个栈,可以使用一个字符串去模拟栈的行为,
注意:将字符串的尾部作为栈的出口,头部作为栈的顶部

栈特别适合做相邻的一些判断,比如相邻字母,相邻括号匹配、消除

python代码

class Solution:
    def removeDuplicates(self, s: str) -> str:
        result = list()
        for c in s:
            if not result or c != result[-1]: # 把result写出s,调试半天orz
                # 如果栈为空或者该元素与栈顶元素不同,直接将要遍历的元素放入即可
                result.append(c)
            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. 逆波兰表达式求值

leetcode题目链接
代码随想录文档讲解

思路

逆波兰表达式-> 后缀表达式(二叉树的后序遍历)
如何用栈实现:

  1. 遇见数字就加入栈
  2. 遇见操作符就将前两个元素取出,进行运算后再加入栈
    整个后缀表达式的结果就是栈的最后唯一一个元素

6//132 结果为 0
6//-132 结果为 -1

python负数整除原则

在Python中,负数整除(//)遵循以下原则:

结果向下取整到最近的整数。

如果除数和被除数都是负数,结果为正。

如果除数和被除数中至少有一个是负数,结果为负。

例如:

-7 // 2 # 结果为 -4
-7 // -2 # 结果为 3
7 // -2 # 结果为 -4

结果总是向下取整到最近的整数,即不大于真实结果的最大整数。如果结果是0,则保留0的符号。

python代码

class Solution:
    def evalRPN(self, tokens: List[str]) -> int:
        result = list()
        for t in tokens:
            if t == '+' or t == '-' or t == '*' or t == '/':
                nums1 = result[-1]
                result.pop()
                nums2 = result[-1]
                result.pop()
                if t == '+':
                    result.append(nums1+nums2)
                elif t== '-':
                    result.append(nums2-nums1)
                elif t== '*':
                    result.append(nums1*nums2)
                else:
                    if nums1*nums2<0: # 两者有一个<0
                        result.append((abs(nums2)//abs(nums1))*(-1))
                    else:
                        result.append(nums2//nums1)
            else:
                result.append(int(t))
        return result[-1]
随想录代码
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()
# 2
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()) # 如果一开始只有一个数,那么会是字符串形式的
  • 25
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值