20. 有效的括号
给定一个只包括
'(',')','{','}','[',']'的字符串s,判断字符串是否有效。 有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
s仅由括号'()[]{}'组成
思路
利用栈 后进先出 的特点进行括号匹配的判断。
- 遍历字符串
s. - 如果遇到左括号,直接入栈,
- 如果遇到右括号,
- 判断当前栈是否为空,
- 如果栈空,意味着没有相应的左括号与当前的右括号匹配,当前字符串无效,返回
false; - 否则,判断当前栈顶元素括号类型是否与当前右括号类型相同,
- 若不同,匹配失败,括号无效,返回
false, - 否则,则将栈顶元素出栈,继续循环。
- 若不同,匹配失败,括号无效,返回
- 循环结束后,所有右括号都有对应顺序的左括号匹配,判断当前栈是否为空,
- 若栈不空,这意味着有多余的左括号存在,括号无效,返回
false, - 若栈空,这意味着字符串的所有括号一一对应,括号有效,返回
true。
- 若栈不空,这意味着有多余的左括号存在,括号无效,返回
代码
class Solution {
public boolean isValid(String s) {
Deque<Character> stack = new LinkedList<>();
for(int i=0;i<s.length();i++){
if(s.charAt(i)=='('||s.charAt(i)=='['||s.charAt(i)=='{'){
stack.push(s.charAt(i));
continue;
}
if(stack.isEmpty()){
return false;
}
if(stack.pop()!=match(s.charAt(i))){
return false;
}
}
return stack.isEmpty() ? true :false;
}
private char match(char bracket){
char res=0;
switch(bracket){
case ')':{
res='(';
break;
}
case '}':{
res='{';
break;
}
case ']':{
res='[';
break;
}
}
return res;
}
}
1047. 删除字符串中的所有相邻重复项
给出由小写字母组成的字符串
S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。 在 S 上反复执行重复项删除操作,直到无法继续删除。 在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
1047. 删除字符串中的所有相邻重复项 - 力扣(Leetcode)
思路
要判断重复项,就要将当前字符与对之前遍历的字符逆序进行判断,需要用到栈的 后进先出 的特点。
- 遍历字符串
s,- 如果当前栈为空或者栈不空,但是栈顶元素与当前元素不相同,这意味着当前元素与它相邻的元素不重复,将当前元素入栈。
- 上述条件不满足,意味着当前元素与相邻元素重复,不断取出栈顶元素与当前元素比较,如果重复,栈顶元素出栈,并重复这种比较,直到栈空,或者栈顶元素与当前元素不相同为止。
- 遍历完成后,将栈的元素全部出栈,此时得到的字符序列是逆序的。
- 将字符序列进行反转,返回结果。
代码
class Solution {
public String removeDuplicates(String s) {
Deque<Character> stack = new LinkedList<>();
for(int i=0;i<s.length();i++){
if(stack.isEmpty()||stack.peek()!=s.charAt(i)){
stack.push(s.charAt(i));
continue;
}
while(!stack.isEmpty()&&stack.peek()==s.charAt(i)){
stack.pop();
}
}
StringBuilder sb = new StringBuilder();
while(!stack.isEmpty()){
sb.append(stack.pop());
}
return sb.reverse().toString();
}
}
150. 逆波兰表达式求值
给你一个字符串数组
tokens,表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。 注意:
- 有效的算符为
'+'、'-'、'*'和'/'。- 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
- 两个整数之间的除法总是 向零截断 。
- 表达式中不含除零运算。
- 输入是一个根据逆波兰表示法表示的算术表达式。
- 答案及所有中间计算结果可以用 32 位 整数表示。
思路
逆波兰表达式的特点是操作数在前,运算符在后,因此,遍历逆波兰表达式时,遇到运算符时,再向前找刚刚遍历的 2 个操作数,同样需要用到栈的 后进先出 的特点。
根据这个特点,遇到运算符时,栈顶元素是这个运算操作的第二个操作数 ,这一点在除法运算中很重要。
算法如下:
- 遍历逆波兰表达式的数组
tokens,- 如果当前元素不是运算符,即当前元素表示整数,则将其转换成整型并入栈;
- 否则,从栈顶依次取出第二个操作数和第一个操作数 ,进行运算,运算格式是 : 结果 = 第一个操作数 运算符 第二个操作数 。
- 将运算结果压入栈中,作为之后运算的操作数。
- 遍历结束后,栈顶元素就是这个表达式的运算结果,取出栈顶元素并返回。
代码
class Solution {
public int evalRPN(String[] tokens) {
Deque<Integer> stack = new LinkedList<>();
int firstNum,secondNum,res;
for(int i=0;i<tokens.length;i++){
if(!isOperations(tokens[i])){
// 不是运算符
// tokens[i] 是 整数
stack.push(Integer.valueOf(tokens[i]));
continue;
}
// tokens[i] 是 运算符
secondNum = stack.pop();
firstNum = stack.pop();
// 计算
if("+".equals(tokens[i])){
res = firstNum + secondNum;
}else if("-".equals(tokens[i])){
res = firstNum - secondNum;
}else if("*".equals(tokens[i])){
res = firstNum * secondNum;
}else{
res =firstNum / secondNum;
}
// 结果压入栈
stack.push(res);
}
return stack.peek();
}
private boolean isOperations(String symbol){
if("+".equals(symbol)||"-".equals(symbol)||
"*".equals(symbol)||"/".equals(symbol)){
return true;
}else{
return false;
}
}
}