给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
示例 1:
输入:s = "()" 输出:true
示例 2:
输入:s = "()[]{}" 输出:true
示例 3:
输入:s = "(]" 输出:false
文章讲解:代码随想录
视频讲解:栈的拿手好戏!| LeetCode:20. 有效的括号_哔哩哔哩_bilibili
第一印象:想不到用什么方法,是懵逼的。
看完讲解:知道了两两匹配的情况用栈更合适。
class Solution {
public boolean isValid(String s) {
Stack<Character> stack;
stack = new Stack<>();
char[] chars = s.toCharArray();
for (int i = 0; i < chars.length; i++) {
if (chars[i] == '(') {
stack.push(')');
} else if (chars[i] == '{') {
stack.push('}');
} else if (chars[i] == '[') {
stack.push(']');
// 这里包含了两种情况,一种是左括号没有相对应的右括号与之对应
// 第二种情况是有右括号但是不是相对应的右括号
} else if (stack.isEmpty() || stack.peek() != chars[i]) {
return false;
} else {
stack.pop();
}
}
return stack.isEmpty();
}
}
给出由小写字母组成的字符串 S
,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
示例:
输入:"abbaca" 输出:"ca" 解释: 例如,在 "abbaca" 中,我们可以删除 "bb" 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 "aaca",其中又只有 "aa" 可以执行重复项删除操作,所以最后的字符串为 "ca"。
文章讲解:代码随想录
视频讲解:栈的好戏还要继续!| LeetCode:1047. 删除字符串中的所有相邻重复项_哔哩哔哩_bilibili
第一印象:看到这道题目其实也是匹配类型的题目,我第一时间就想到了栈,我用栈做了出来但是栈在最后输出的时候会有些麻烦,因为出栈的时候是反着出,所以我改变思路用了Deque双向队列在完成了这道题目。另外我也有在思考这道题目双指针是否能做,看了讲解之后发现确实可以。
看完讲解:这道题算是有效的括号的拓展了。
栈:
// 使用Deque来实现
class Solution {
public String removeDuplicates(String s) {
Deque<Character> deque = new ArrayDeque<>();
char[] chars = s.toCharArray();
for (int i = 0; i < chars.length; i++) {
if (deque.isEmpty() || chars[i] != deque.getLast()) {
deque.addLast(chars[i]);
} else {
deque.removeLast();
}
}
String str = "";
while (!deque.isEmpty()) {
str += deque.removeFirst();
}
return str;
}
}
双指针:
// 使用双指针实现
class Solution {
public String removeDuplicates(String s) {
char[] chars = s.toCharArray();
int fast = 0;
int slow = 0;
while (fast < s.length()) {
chars[slow] = chars[fast];
if (slow > 0 && chars[slow] == chars[slow - 1]) {
slow--;
} else {
slow++;
}
fast++;
}
return new String(chars, 0, slow); // 0表示起始下标,slow表示终止下标
}
}
给你一个字符串数组 tokens
,表示一个根据 逆波兰表示法 表示的算术表达式。
请你计算该表达式。返回一个表示表达式值的整数。
注意:
- 有效的算符为
'+'
、'-'
、'*'
和'/'
。 - 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
- 两个整数之间的除法总是 向零截断 。
- 表达式中不含除零运算。
- 输入是一个根据逆波兰表示法表示的算术表达式。
- 答案及所有中间计算结果可以用 32 位 整数表示。
示例 1:
输入:tokens = ["2","1","+","3","*"] 输出:9 解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
文章讲解:代码随想录
视频讲解:栈的最后表演! | LeetCode:150. 逆波兰表达式求值_哔哩哔哩_bilibili
第一印象:不明白为什么要用这么复杂的形式来作为计算的表达式。
看完讲解:对于人类来说,日常的表达式更好理解,但对于计算机来说,内存大多是栈式结构,用
逆波兰表达式更适合计算机。
class Solution {
public int evalRPN(String[] tokens) {
Stack<Integer> stack = new Stack<>();
for (String s : tokens) {
if ("+".equals(s)) {
stack.push(stack.pop() + stack.pop());
} else if ("-".equals(s)) {
stack.push(-stack.pop() + stack.pop());
} else if ("*".equals(s)) {
stack.push(stack.pop() * stack.pop());
} else if ("/".equals(s)) {
int temp1 = stack.pop();
int temp2 = stack.pop();
stack.push(temp2 / temp1);
} else {
stack.push(Integer.valueOf(s));
}
}
return stack.pop();
}
}
今日小结:这几道题都是对栈的拓展,加深了对于栈的理解,下次遇到栈相关的题目都不会再害怕了,当然也要经常复习。