于2021.11.25记录。
栈的特性:先入后出,入栈和出栈操作只能在栈顶完成
队列的特性:先入后出,入队是在队尾实现的,出队是在队头实现的。
1. java中常用的方法总结
下面以java语言为例,列出来了栈和队列中一些常用的方法,后面刷题中也会用到这些方法。
(1)栈的常用方法
方法 | 作用 |
---|---|
Stack() | 定义一个空栈 |
boolean empty() | 判断堆栈是否为空 |
Object push(Object element) | 把元素压入堆栈顶部 |
Object pop( ) | 移除堆栈顶部的对象 |
Object peek( ) | 查看堆栈顶部的对象,但不从堆栈中移除它 |
size() | 返回栈中元素的个数 |
int search(Object element) | 返回对象在堆栈中的位置,以 1 为基数 |
(2)队列的常用方法
方法 | 作用 |
---|---|
add() | 入队(若失败则抛出IllegalStateException异常) |
element() | 获取队头的值,但不出队(若队列为空则抛出异常NoSuchElementException) |
remove() | 获取并移除队头(若队列空则抛出NoSuchElementException异常) |
offer() | 将指定元素插入队列 |
peek() | 返回该对象获取队头的值,但不出队 |
poll() | 获取并移除队头 |
20. 有效的括号
本题总结起来,不匹配的就三种情况:
①左侧符号多余
②右侧符号多余
③数量上可以配对,但是符号不匹配。
1.1 解法1:普通入栈
思路:当前是什么符号,就将什么符号入栈
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for(int i = 0;i < s.length();i++){
char cur = s.charAt(i);
if(cur == '(' || cur == '[' || cur == '{'){
stack.push(cur);
}
else if(cur == ')'){
if(stack.empty()) return false; //对应上面不匹配的情况二
if(!stack.empty()){
char popVal = stack.pop();
if(popVal != '(') return false; //对应上面不匹配的情况三
}
}
else if(cur == ']'){
if(stack.empty()) return false;
if(!stack.empty()){
char popVal = stack.pop();
if(popVal != '[') return false;
}
}
else if(cur == '}'){
if(stack.empty()) return false;
if(!stack.empty()){
char popVal = stack.pop();
if(popVal != '{') return false;
}
}
}
return stack.empty(); //对应上面不匹配的情况一
}
}
1.2 解法2:置换入栈
思路:当前是什么符号,就让其对应的右半符号入栈
class Solution {
public boolean isValid(String s) {
Stack<Character> stack = new Stack<>();
for(int i = 0;i < s.length();i++){
char cur = s.charAt(i);
if(cur == '('){
stack.push(')');
}
else if(cur == '['){
stack.push(']');
}
else if(cur == '{'){
stack.push('}');
}
else if(stack.empty() || cur != stack.peek()){
return false;
}
else{
stack.pop();
}
}
return stack.empty();
}
}
150. 逆波兰表达式求值
逆波兰表达式,又称为后缀表达式。以前我们常见的是中缀表达式,比如(2 + 1) * 3,转换为逆波兰表达式为[2 1 + 3 *]。
思路:遇到操作数入栈,遇到运算符出栈。
-
创建一个栈,用于存放运算符两侧的操作数
-
从左到右遍历逆波兰表达式,获取每一个字符串
-
如果该字符不是4种运算符,那么就将操作数入栈;
如果该字符是运算符,那么从栈中弹出两个操作数i1和i2,根据运算符的种类,计算i2和i1得到result(注:这里有一个易错点,i1是先弹出的,i2是后弹出的,在运算时,应该是i2-i1,而不应该是i1-i2,这一点需要注意下),然后将result入栈。
-
遍历结束后,将栈中的元素出栈并返回。
class Solution {
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>();
Integer i1;
Integer i2;
Integer result;
for(int i = 0;i < tokens.length;i++){
String cur = tokens[i];
switch(cur){
case "+":
i1 = stack.pop();
i2 = stack.pop();
result = i2 + i1;
stack.push(result);
break;
case "-":
i1 = stack.pop();
i2 = stack.pop();
result = i2 - i1;
stack.push(result);
break;
case "*":
i1 = stack.pop();
i2 = stack.pop();
result = i2 * i1;
stack.push(result);
break;
case "/":
i1 = stack.pop();
i2 = stack.pop();
result = i2 / i1;
stack.push(result);
break;
default:
stack.push(Integer.parseInt(cur));
break;
}
}
return stack.pop();
}
}
注:由于这个栈中存放的是操作数,是Integer类型的,而从字符串中得到的是String类型的,因此要将String类型转换为Integer类型(基本数据类型),就用到了Integer.parseInt()。
这里也可以回顾下如何将Integer类型(基本数据类型)转换为String类型?方法一:直接在末尾+“ ”即可;方法二:使用String.valueOf()进行转换。