文章目录
前言
教程链接
💛栈这种结构非常适合做相邻字符的操作,包括消除、匹配、计算等
20. 有效的括号
三种不匹配的情况
思路
第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false
第二种情况:遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false
第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false
总体思路:如果是true的情况, 中间遍历的过程中一定有一个是与stack的top元素匹配 【到了对称的地方了】, 那么这个匹配的就可以pop出去,且紧跟着后面的应该也是匹配的;
压栈进去的是左边括号
💖小技巧: 压栈进去的是左边的括号,但是存的时候使用右边括号,这样后续判断快一些。
剪枝:如果是奇数大小的话,那一定不匹配
时间复杂度: O(n)
空间复杂度: O(n)
方法一 只使用栈
自己写的注意点
- elif not stack or ele != stack[-1]:#注意两个条件的顺序不能颠倒
- 再记一下:注意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数据结构课程里面学过,所以理解的很快,也很简单
💖总体思路:使用栈,遇到数字压栈,遇到运算符就弹出两个数字将计算结果压栈;
方法一
写代码小细节
- 判断是否为运算符,可以在+、-、*、/里面先比较,如果不是就是数字啦
- 💘第一个出来的在运算符后面【非常重要】
- 可以用eval:eval(f’{second_num} {item} {first_num}’ – 执行字符串
- f表示string,{}是占位符
- 也可以使用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()) # 如果一开始只有一个数,那么会是字符串形式的
总结
今天这个也是很简单,多到时间把数据结构的二叉树学完;