代码随想录算法训练营第11天|栈与队列| 20. 有效的括号 、1047. 删除字符串中的所有相邻重复项、150. 逆波兰表达式求值
20. 有效的括号
题目链接: 20. 有效的括号
自己做
思想:
是左括号,就进栈,遇到右括号,就出栈,一旦发现不匹配,就失败
自己做时,一些特殊的情况没有考虑到,导致不能一边运行成功。
代码:
python
class Solution(object):
def isValid(self, s):
"""
:type s: str
:rtype: bool
"""
# 思想:
'''
是左括号,就进栈,遇到有括号,就出栈,一旦发现不匹配,就失败
'''
if len(s) == 0:
return False
stack = []
for i in range(len(s)):
if s[i] == '(' or s[i] == '{' or s[i] == '[':
stack.append(s[i])
elif s[i] == ')' and len(stack) != 0:
val = stack.pop()
if val == '(':
continue
else:
return False
elif s[i] == '}' and len(stack) != 0:
val = stack.pop()
if val == '{':
continue
else:
return False
elif s[i] == ']' and len(stack) != 0:
val = stack.pop()
if val == '[':
continue
else:
return False
else:
return False
if not stack:
return True
else:
return False
代码随想录
思想:
建议在写代码之前要分析好有哪几种不匹配的情况,如果不在动手之前分析好,写出的代码也会有很多问题。
有三种不匹配的情况:
-
左方向的括号多余了
已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false
-
括号没有多余,但是 括号的类型没有匹配上
遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false
-
右方向的括号多余了
遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false
代码:
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
else:
stack.pop()
return True if not stack else False
c++
class Solution {
public:
bool isValid(string s) {
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() && s[i] == st.top()){
st.pop();
}else{ //第二种第三种情况
return false;
}
}
if(!st.empty()){//第一种情况
return false;
}
return true;
/* 也可以这样写
return st.empty();
*/
}
};
1047. 删除字符串中的所有相邻重复项
题目链接: 1047. 删除字符串中的所有相邻重复项
自己做
思想:
这道题比较简单,只需要循环到当前元素时,将栈顶的元素取出来进行比较再进行下一步操作就好了。
代码:
python
class Solution(object):
def removeDuplicates(self, s):
"""
:type s: str
:rtype: str
"""
stack = []
for char in s:
# 如果stack==[]直接进栈
if not stack:
stack.append(char)
else:
val = stack.pop()
if val == char:
continue
else:
stack.append(val)
stack.append(char)
return ''.join(stack)
代码随想录
思想:
和自己想的一样,想法比较好想到
代码:
# 方法一,使用栈
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)
return "".join(res) # 字符串拼接
注意:
递归的实现就是
每一次递归调用都会把函数的局部变量、参数值和返回地址等压入调用栈中,然后递归返回的时候,从栈顶弹出上一次递归的各项参数,所以这就是递归为什么可以返回上一层位置的原因。
c++
class Solution {
public:
string removeDuplicates(string s) {
stack<char> st;
for(int i = 0; i < s.size(); i++){
if(!st.empty() && s[i] == st.top()){
//出栈
st.pop();
}else{
st.push(s[i]);
}
}
string res = "";
while(!st.empty()){
res += st.top();
st.pop();
}
reverse(res.begin(), res.end());
return res;
}
};
150. 逆波兰表达式求值
题目链接: 150. 逆波兰表达式求值
** 自己做**
思想:
逆波兰表达式其实就是标准算数表达式即中序遍历的后序遍历形式,这个用栈来解决!
但是题中强调两个整数之间的除法总是 向零截断 ,这地方需要特殊处理
代码:
python
import math
class Solution(object):
def compute(self, num1, num2, char):
if char == '+':
return num1 + num2
elif char == '-':
return num1 - num2
elif char == '*':
return num1 * num2
elif char == '/':
#print(int((float(num1)/float(num2))))
return int((float(num1)/float(num2)))
def evalRPN(self, tokens):
"""
:type tokens: List[str]
:rtype: int
"""
stack = []
for char in tokens:
if char in ['+', '-', '*', '/']:
# 出栈两个,进行运算,结果压入栈中
num2 = stack.pop()
num1 = stack.pop()
result = self.compute(num1, num2, char)
stack.append(result)
else:
stack.append(int(char))
return stack.pop()
代码随想录
思想:
给你一个后缀遍历的表达式字符串数组,让你计算这个表达式的值,要想到用栈来解决
语言熟知就进栈,遇到符号就出栈,计算结果,再把结果压入栈,最后栈里面的数值就是整个表达式的结果
代码:
本题代码随想录给的代码**两个整数之间的除法总是 向零截断 **部分的处理错误
python
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()
c++
注意:
做题时有以下几点困惑:
c++中string 类型,是类的实例吗,还是基本数据类型…
答:是类,初始化就是实例
string类型" "如何转换成char’ '类型
答:后面慢慢解答吧
char ’ ’ 类型的数字如何转换成 int 类型的数值
答:固定函数stoi, stol, stoll, 也可以自己实现力扣18
想用switch函数来判断符号来着,但是说switch©c不能为字符串类型,那什么类型符合呢?
class Solution {
public:
int evalRPN(vector<string>& tokens) {
stack<int> st;
for(int i = 0; i < tokens.size(); i++){
if(tokens[i] == "+" || tokens[i] == "-" || tokens[i] == "*" || tokens[i] == "/"){
int nums1 = st.top();
st.pop();
int nums2 = st.top();
st.pop();
if(tokens[i] == "+") st.push(nums2 + nums1);
if(tokens[i] == "-") st.push(nums2 - nums1);
if(tokens[i] == "*") st.push(nums2 * nums1);
if(tokens[i] == "/") st.push(nums2 / nums1);
}else{
st.push(stoi(tokens[i]));
}
}
return st.top();
}
};