题目列表
解题过程
1、20.有效的括号
给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
思路: 将字符串中的元素入栈,一边入栈一边判断当前元素和已入栈元素是否匹配,如果是,就出栈;如果不是,就继续入栈。遍历完字符串后,判断栈是否为空。
class Solution {
public boolean isValid(String s) {
Deque<Character> deque = new LinkedList<>();
char ch;
for (int i = 0; i < s.length(); i++) {
ch = s.charAt(i);
//如果当前字符是左括号,就把右括号入栈
if (ch == '(') {
deque.push(')');
} else if (ch == '{') {
deque.push('}');
} else if (ch == '[') {
deque.push(']');
} else if (deque.isEmpty() || deque.peek() != ch) { //当遇到右括号时,栈中一定要有相匹配的左括号,如果为空或者栈顶元素不匹配,就说明不是有效的括号
return false;
} else { //当前字符为右括号,判断是否和栈顶元素匹配(前面已经判断是否匹配,这里直接弹出就行)
deque.pop();
}
}
//字符串遍历完,栈为空,返回真
return deque.isEmpty();
}
}
2、1047.删除字符串中的所有相邻重复项
给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
思路: :有点像消消乐。还是用栈来做。
class Solution {
public String removeDuplicates(String s) {
Deque<Character> deque = new LinkedList<>();
char ch;
for (int i = 0; i < s.length(); i++) {
ch = s.charAt(i);
if (!deque.isEmpty() && ch == deque.peek()) {
deque.pop();
continue;
}
deque.push(ch);
}
String str = "";
//弹出栈中剩余元素
while (!deque.isEmpty()) {
str = deque.pop() + str;
}
return str;
}
}
用字符串做,可省略栈转化为字符串的过程
class Solution {
public String removeDuplicates(String s) {
// 将 res 当做栈
// 也可以用 StringBuilder 来修改字符串,速度更快
// StringBuilder res = new StringBuilder();
StringBuffer res = new StringBuffer();
// top为 res 的长度
int top = -1;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// 当 top > 0,即栈中有字符时,当前字符如果和栈中字符相等,弹出栈顶字符,同时 top--
if (top >= 0 && res.charAt(top) == c) {
res.deleteCharAt(top);
top--;
// 否则,将该字符 入栈,同时top++
} else {
res.append(c);
top++;
}
}
return res.toString();
}
}
用双指针来做
class Solution {
public String removeDuplicates(String s) {
char[] ch = s.toCharArray();
int fast = 0;
int slow = 0;
while(fast < s.length()){
// 直接用fast指针覆盖slow指针的值
ch[slow] = ch[fast];
// 遇到前后相同值的,就跳过,即slow指针后退一步,下次循环就可以直接被覆盖掉了
if(slow > 0 && ch[slow] == ch[slow - 1]){
slow--;
}else{
slow++;
}
fast++;
}
return new String(ch,0,slow);
}
}
3、150.逆波兰表达式求值
给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意:
- 有效的算符为
'+'、'-'、'*'和'/'。 - 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
- 两个整数之间的除法总是 向零截断 。
- 表达式中不含除零运算。
- 输入是一个根据逆波兰表示法表示的算术表达式。
- 答案及所有中间计算结果可以用 32 位 整数表示。
思路: 元素逐个入栈,遇到运算符,从栈中弹出两个元素,做相应运算后将结果入栈,依此类推,直到数组元素全部遍历完,这时栈中元素值就是答案。
class Solution {
public int evalRPN(String[] tokens) {
Deque<Integer> deque = new LinkedList<>();
for (String str : tokens) {
if (!"+".equals(str) && !"-".equals(str) && !"*".equals(str) && !"/".equals(str)) { //当前元素是数字
deque.push(Integer.valueOf(str)); //字符转换为整数
} else {
int intB = deque.pop();
int intA = deque.pop();
if ("+".equals(str)) {
deque.push(intA + intB);
} else if ("-".equals(str)) {
deque.push(intA - intB);
} else if ("*".equals(str)) {
deque.push(intA * intB);
} else {
deque.push(intA / intB);
}
}
}
return deque.pop();
}
}
注意
- leetcode中不能用==判断字符串是否相等;
- 字符串到整数类型的转换。
总结
今天是栈的经典应用题目。