1 什么是栈?什么是队列?
栈和队列想必大家已经很熟悉了。栈就是一个先进后出的数据结构,而队列是先进先出的数据结构。具体如下图所示。
栈和队列是我们解决很多算法问题很好的工具 ,例如,解决树相关问题的时候,经常需要用到栈和队列。所以,我们需要多做一些题,熟悉一下这两个数据结构。
2. 相关题目
这道题目,我曾经在校招面试遇到过,碰到就相当于送分了。
给定一个字符串,这个字符串中只包含'(',')
','{
','}
','[
',']
' ,判断对号是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
public boolean isValid(String s) {
char[] chars = s.toCharArray();
Stack<Character> characters = new Stack<>();
for (int i = 0; i < chars.length; i++) {
if (!characters.isEmpty() && characters.peek() == chars[i]) {
characters.pop();
continue;
}
if (chars[i] == '(') {
characters.push(')');
} else if (chars[i] == '[') {
characters.push(']');
} else if (chars[i] == '{') {
characters.push('}');
} else {
return false;
}
}
return characters.isEmpty();
}
这道题最好的办法就是用栈去做,当我们遇到'(','{
','[
',就把')
','}
',']
',遍历的过程中如果碰到')
','}
',']
',就去栈的头找是否和当前字符相同,相同就一起消掉,不相同就属于失效,类似于消消乐。
给出由小写字母组成的字符串 s,重复项删除操作会选择两个相邻且相同的字母,并删除它们。在 s 上反复执行重复项删除操作,直到无法继续删除。在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
public static String removeDuplicates(String s) {
Stack<Character> stack = new Stack<>();
for (int i = 0; i < s.length(); i++) {
if (!stack.isEmpty() && stack.peek() == s.charAt(i)) {
stack.pop();
} else {
stack.push(s.charAt(i));
}
}
int size = stack.size();
String result = "";
for (int i = 0; i < size; i++) {
result = stack.pop() + result;
}
return result;
}
这道题与上一题类似,先把字母放到栈里面,后面遍历时如果和栈头字母相同,就一起消掉,否则就如栈。
给你一个字符串数组 tokens
,表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意:
- 有效的算符为
'+'
、'-'
、'*'
和'/'
。 - 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
- 两个整数之间的除法总是 向零截断 。
- 表达式中不含除零运算。
- 输入是一个根据逆波兰表示法表示的算术表达式。
- 答案及所有中间计算结果可以用 32 位 整数表示。
这道题虽然官网标的是中等题,但是如果用栈来做的话,其实就是简单题难度。大家可能之前不了解逆波兰表达式,所以会不知所措,仔细阅读后就能知道,就是我们在遍历字符串数组的时候,一旦遇到运算符,就把这个运算符前面两个数取出来,进行运算。如果一个字符串数组中出现多个运算符,就需要先把前面的先算出结果来,然后那这个结果去和后面的进行计算,就相当于加了小括号。
那么我们如何操作呢?
还是用到栈,先将两个数存到栈里面,然后如果遇到运算符,就把两个数弹出来,根据运算符进行计算,再把计算结果压进栈中;后面如果再来了一个数,紧接着又来了一个运算符,就可以继续把两个数取出来运算,是不是相当于加了小括号呢。
具体代码如下:
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>();
int sum = 0;
stack.push(Integer.parseInt(tokens[0]));
for (int i = 1; i < tokens.length; i++) {
if ("+".equals(tokens[i])) {
Integer right = stack.pop();
Integer left = stack.pop();
stack.push(left + right);
} else if ("-".equals(tokens[i])) {
Integer right = stack.pop();
Integer left = stack.pop();
stack.push(left - right);
} else if ("*".equals(tokens[i])) {
Integer right = stack.pop();
Integer left = stack.pop();
stack.push(left * right);
} else if ("/".equals(tokens[i])) {
Integer right = stack.pop();
Integer left = stack.pop();
stack.push(left / right);
} else {
stack.push(Integer.parseInt(tokens[i]));
}
}
return stack.pop();
}