今日任务
力扣
- 20. 有效的括号
- 1047. 删除字符串中的所有相邻重复项
- 150. 逆波兰表达式求值
看了答案很疑惑为啥要用Deque而不是Stack,就去搜了一下:
【Java】Java双端队列Deque使用详解_dequeuejava-CSDN博客
题目 :20. 有效的括号
思路
使用stack解决
题解
class Solution {
public boolean isValid(String s) {
// 不匹配的场景: 数量不相等、括号类型不一样、括号类型数量不匹配
char[] chars = s.toCharArray();
Stack<Character> stack = new Stack<>();
for (char c : chars) {
if (c == '(') {
stack.push(')');
} else if (c == '{') {
stack.push('}');
} else if (c == '[') {
stack.push(']');
} else if (stack.isEmpty() || stack.peek() != c) {
return false;
} else {
stack.pop();
}
}
return stack.isEmpty();
}
}
题目 :1047. 删除字符串中的所有相邻重复项
思路
就是两两比较
题解
1.基础stack操作
class Solution {
public String removeDuplicates(String s) {
char[] chars = s.toCharArray();
Stack<Character> stack = new Stack<>();
for (char c: chars) {
if (!stack.isEmpty() && stack.peek() == c) {
// 如果当前字符和栈顶字符相同,则弹出栈顶元素,不将当前字符压栈
stack.pop();
} else {
// 如果不相同,将当前字符压栈
stack.push(c);
}
}
// 构建最终字符串
StringBuilder str = new StringBuilder();
while (!stack.isEmpty()) {
str.insert(0, stack.pop());
}
return str.toString();
}
}
2.拿字符串直接作为栈,省去了栈还要转为字符串的操作。
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();
}
}
3.利用了双指针技巧来高效地解决删除字符串中所有相邻重复项的问题。
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);
}
}
代码解释
这段代码利用了双指针技巧来高效地解决删除字符串中所有相邻重复项的问题。这里的两个指针是 fast
和 slow
,它们都从字符串的开始位置出发。fast
指针用于遍历字符串,而 slow
指针用于构建最终的结果字符串。这个方法有效地利用了输入字符串的字符数组 ch
来进行原地修改,从而避免了使用额外的栈结构。下面是代码的逐行解释:
-
char[] ch = s.toCharArray();
: 将输入字符串s
转换为字符数组ch
,以便进行原地修改。 -
int fast = 0, slow = 0;
: 初始化两个指针fast
和slow
,它们都从数组的开始位置出发。 -
while(fast < s.length()){
: 使用fast
指针遍历整个字符数组。 -
ch[slow] = ch[fast];
: 将fast
指针指向的字符复制到slow
指针的位置。这样做的目的是将当前遍历到的字符放到结果字符串的正确位置上。 -
if(slow > 0 && ch[slow] == ch[slow - 1]){
: 检查slow
指针当前指向的字符是否与其前一个字符相同。这一步是用来判断是否存在相邻的重复字符。-
slow--;
: 如果当前字符与前一个字符相同,则通过将slow
指针减一来“删除”当前字符。这实际上是通过后续的覆盖操作来实现的,因为后面的字符将会覆盖当前slow
指针指向的位置。 -
else { slow++; }
: 如果当前字符与前一个字符不同,则将slow
指针向前移动一位,为下一个可能的非重复字符预留位置。
-
-
fast++;
: 无论当前字符是否被删除,fast
指针都向前移动一位,以继续遍历字符数组。 -
return new String(ch, 0, slow);
: 最后,使用字符数组ch
的前slow
个字符创建一个新的字符串并返回。这里的slow
指针实际上代表了最终结果字符串的长度。
这个方法的巧妙之处在于它同时完成了遍历和修改操作,通过 slow
指针来控制结果字符串的构建过程,有效地去除了所有相邻的重复字符。通过在原数组上进行操作,避免了额外空间的使用,实现了空间复杂度为 O(1) 的解决方案。
题目 :150. 逆波兰表达式求值
思路
逆波兰式_百度百科 (baidu.com)
说了一大堆,就是编码实现:
注意减法和除法。 由于栈的FIFO所以是先出栈的是除数 后出栈的被除数
别问我怎么知道除法是要这样做的!!!!!
题解
class Solution {
public int evalRPN(String[] tokens) {
// 计算方式 新建一个表达式,如果当前字符为变量或者为数字,则压栈,如果是运算符,
// 则将栈顶两个元素弹出作相应运算,结果再入栈,最后当表达式扫描完后,栈里的就是结果。
// 如何去区分优先级?
Deque<Integer> stack = new LinkedList<>();
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();
}
}