代码随想录Day11
20.有效的括号
-
初始化一个栈 stack 和一个哈希表 map。栈用于存储左括号,哈希表用于存储括号及其对应的标识。
-
填充哈希表 map,将左括号和右括号映射为不同的整数。这里将左括号映射为 1、2、3,而将对应的右括号映射为 4、5、6。
-
遍历字符串 s 中的每个字符。
-
对于每个字符 c,检查它是否在哈希表 map 中。如果不在,则将其视为无效字符,将变量 a 设置为 false 并退出循环。
-
如果 c 是左括号(即 map.getOrDefault(c, -1) 的值在 1 到 3 之间),则将其压入栈中。
-
如果 c 是右括号,则检查栈是否为空以及栈顶的左括号是否与当前右括号匹配。匹配的条件是 map.get(stack.peek()) ==
flag - 3。如果匹配,则弹出栈顶的左括号;如果不匹配或栈为空,则将变量 a 设置为 false 并退出循环。 -
遍历完字符串 s 后,检查栈是否为空。如果栈不为空,则说明还有未匹配的左括号,将变量 a 设置为 false。
-
返回变量 a 的值。如果 a 为 true,则括号序列有效;如果为 false,则括号序列无效。
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
Map<Character,Integer> map = new HashMap<Character,Integer>();
boolean a = true;
//给map中填入数据(key,value)
map.put('(', 1);
map.put('[', 2);
map.put('{', 3);
map.put(')', 4);
map.put(']', 5);
map.put('}', 6);
//根据c获取对应的value值,如果c不在map中返回-1
for(char c : s.toCharArray()){
//根据
Integer flag = map.getOrDefault(c,-1);
//左括号入栈
if(flag >= 1 && flag <=3){
stack.push(c);
}
//右括号,栈顶是对应左括号时直接出栈
else if (!stack.isEmpty() && map.get(stack.peek()) == flag - 3) {
stack.pop();
}
//右括号,但栈为空or栈顶不是对应左括号,退出循环
else{
a = false;
break;
}
}
//栈不为空,还有左括号
if(!stack.isEmpty()){
a = false;
}
return a;
}
}
1047.删除字符串中的所有相邻重复项
该题要求去除字符串中的相邻重复字符。具体做法是利用栈的特性,在遍历字符串时,根据栈顶元素与当前字符的对比,决定是否将当前字符入栈。
-
首先,我们创建一个栈 stack 来存储字符。然后,遍历字符串 s 中的每个字符 c。
-
对于每个字符 c,我们检查栈是否为空或者栈顶元素是否与 c 不同。如果满足这两个条件之一,说明 c 不是与栈顶相邻的重复字符,因此我们将c 入栈。
-
如果栈不为空且栈顶元素与 c 相同,说明 c 是与栈顶相邻的重复字符,我们执行出栈操作,即 stack.pop(),以去除这个重复字符。
-
遍历完整个字符串后,栈中剩余的字符就是去除相邻重复字符后的结果。然而,由于栈是后进先出的数据结构,我们还需要将栈中的字符按照正确的顺序组合成字符串。
-
为此,我们使用 StringBuilder 来构建结果字符串。通过循环,将栈中的字符依次弹出并添加到 StringBuilder
中。最后,由于栈是反向存储的,我们需要调用 StringBuilder 的 reverse() 方法来反转字符串,得到最终的结果。
class Solution {
public String removeDuplicates(String s) {
Stack<Character> stack = new Stack<>();
for(char c : s.toCharArray()){
//如果栈为空或者与栈顶元素不相同,入栈
if(stack.isEmpty() || c != stack.peek()){
stack.push(c);
}else{
stack.pop(); //与栈顶相同说明为相邻重复元素
}
}
// 使用StringBuilder来构建结果字符串
StringBuilder stringBuilder = new StringBuilder();
// 将栈中的元素依次添加到StringBuilder中
while (!stack.isEmpty()) {
stringBuilder.append(stack.pop());
}
// StringBuilder已经以正确的顺序包含所有字符,不需要反转
return stringBuilder.reverse().toString();
}
}
150.逆波兰表达式求值
对逆波兰表达式求值的过程是:
如果遇到数字就进栈;
如果遇到操作符,就从栈顶弹出两个数字分别为栈顶(a)、栈中的第二个元素(b);
计算 b 运算符 a
- 首先,我们创建一个整数栈 stack,用于存放数字和中间结果。然后,遍历输入的逆波兰表达式字符串数组 tokens。
- 对于数组中的每个元素,我们进行如下判断:
- 如果元素是运算符(即 +、-、* 或 /),我们从栈中弹出两个数字。由于栈是后进先出的数据结构,弹出的第一个数字是栈顶元素,记作a,弹出的第二个数字是栈中原本位于 a 下方的元素,记作 b。接着,根据运算符进行相应的运算,并将运算结果推回栈中。
- 如果元素是数字,我们直接将其转换为整数,并推入栈中。
- 遍历完所有元素后,栈中应该只剩下一个元素,这个元素即为逆波兰表达式的计算结果。我们将其从栈中弹出并返回。
class Solution {
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>();
for(String s : tokens){
//如果是运算符,拿出栈顶的两个元素,然后将二者计算结果在放入栈中
if("+-*/".contains(s)){
int a = stack.pop();
int b = stack.pop();
switch(s){
case"+":
stack.push(b + a);
break;
case"-":
stack.push(b - a);
break;
case"*":
stack.push(b * a);
break;
case"/":
stack.push(b / a);
break;
}
}else{
//数字直接进栈
stack.push(Integer.parseInt(s));
}
}
return stack.pop();
}
}