代码随想录-035期-算法训练营【博客笔记汇总表】-CSDN博客
第五章 栈与队列part02
今日内容: ● 20. 有效的括号
● 1047. 删除字符串中的所有相邻重复项
● 150. 逆波兰表达式求值详细布置 20. 有效的括号 讲完了栈实现队列,队列实现栈,接下来就是栈的经典应用了。 大家先自己思考一下 有哪些不匹配的场景,在看视频 我讲的都有哪些场景,落实到代码其实就容易很多了。题目链接/文章讲解/视频讲解:https://programmercarl.com/0020.%E6%9C%89%E6%95%88%E7%9A%84%E6%8B%AC%E5%8F%B7.html 1047. 删除字符串中的所有相邻重复项 栈的经典应用。 要知道栈为什么适合做这种类似于爱消除的操作,因为栈帮助我们记录了 遍历数组当前元素时候,前一个元素是什么。题目链接/文章讲解/视频讲解:https://programmercarl.com/1047.%E5%88%A0%E9%99%A4%E5%AD%97%E7%AC%A6%E4%B8%B2%E4%B8%AD%E7%9A%84%E6%89%80%E6%9C%89%E7%9B%B8%E9%82%BB%E9%87%8D%E5%A4%8D%E9%A1%B9.html150. 逆波兰表达式求值 本题不难,但第一次做的话,会很难想到,所以先看视频,了解思路再去做题 题目链接/文章讲解/视频讲解:https://programmercarl.com/0150.%E9%80%86%E6%B3%A2%E5%85%B0%E8%A1%A8%E8%BE%BE%E5%BC%8F%E6%B1%82%E5%80%BC.html
目录
0020_有效的括号
1047_删除字符串中的所有相邻重复项
1、ArrayDeque
2、StringBuffer对象
3、char[]用法
0150_逆波兰表达式求值
1、==操作符与equals()方法
2、Character.isDigit(char ch)
0020_有效的括号
写的过程中有很多情况没有考虑到位,导致错了四次。
import java.util.Deque;
import java.util.LinkedList;
import java.util.Stack;class Solution0020 {public boolean isValid(String s) {if (s.length() % 2 != 0) {return false;}Stack<Character> stack = new Stack<>();for (int i = 0; i < s.length(); i++) {char ch = s.charAt(i);if (ch == '(' || ch == '[' || ch == '{') {stack.push(ch);} else if (ch == ')') {if (stack.isEmpty()) {return false;}if (!stack.isEmpty() && stack.pop() != '(') {return false;}} else if (ch == ']') {if (stack.isEmpty()) {return false;}if (!stack.isEmpty() && stack.pop() != '[') {return false;}} else if (ch == '}') {if (stack.isEmpty()) {return false;}if (!stack.isEmpty() && stack.pop() != '{') {return false;}}}if (stack.isEmpty()) {return true;} else {return false;}}public boolean isValid2(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();}
}
1047_删除字符串中的所有相邻重复项
1、ArrayDeque
//ArrayDeque会比LinkedList在除了删除元素这一点外,会快一点。
是的,
ArrayDeque
在除了删除元素之外的大多数操作上通常会比LinkedList
快一些。这是因为ArrayDeque
使用数组作为其内部数据结构,而LinkedList
使用链表。
//参考:https://stackoverflow.com/questions/6163166/why-is-arraydeque-better-than-linkedlist
ArrayDeque<Character> deque = new ArrayDeque<>();//使用 Deque 作为堆栈
2、StringBuffer对象
也可以用 StringBuilder 来修改字符串,速度更快
StringBuffer res = new StringBuffer();
res.deleteCharAt(top);
这段代码首先创建了一个
StringBuffer
对象res
,然后调用了该对象的deleteCharAt(top)
方法。
deleteCharAt(int index)
方法用于删除指定索引位置的字符,其中index
参数表示要删除的字符在字符串缓冲区中的位置。在这段代码中,top
是一个变量,用来表示要删除的字符的索引位置。因此,这行代码的作用是删除
res
字符串缓冲区中索引为top
的字符。
StringBuffer
是 Java 中用于处理可变字符串的类,它允许在字符串中进行插入、追加、删除和修改等操作,而不会创建新的字符串对象。下面是一些StringBuffer
的常用方法:
append(String str)
:将指定的字符串追加到字符串缓冲区的末尾。
StringBuffer sb = new StringBuffer("Hello"); sb.append(" World"); System.out.println(sb.toString()); // 输出: Hello World
insert(int offset, String str)
:在指定的位置插入指定的字符串。
StringBuffer sb = new StringBuffer("Hello"); sb.insert(5, " World"); System.out.println(sb.toString()); // 输出: Hello World
delete(int start, int end)
:删除从start
到end-1
位置的字符。
StringBuffer sb = new StringBuffer("Hello World"); sb.delete(5, 11); System.out.println(sb.toString()); // 输出: Hello
deleteCharAt(int index)
:删除指定位置的字符。
StringBuffer sb = new StringBuffer("Hello World"); sb.deleteCharAt(5); System.out.println(sb.toString()); // 输出: Hell World
replace(int start, int end, String str)
:用新字符串替换指定位置的字符序列。
StringBuffer sb = new StringBuffer("Hello World"); sb.replace(6, 11, "Java"); System.out.println(sb.toString()); // 输出: Hello Java
reverse()
:反转字符串。
StringBuffer sb = new StringBuffer("Hello"); sb.reverse(); System.out.println(sb.toString()); // 输出: olleH
StringBuffer
与StringBuilder
类似,但是StringBuffer
是线程安全的,因为它的方法都是同步的。因此,在单线程环境下,推荐使用StringBuilder
,因为它的性能更好。
3、char[]用法
char[] ch = s.toCharArray();
return new String(ch, 0, slow);
在这段代码中,
new String(ch, 0, slow)
是用来创建一个新的字符串对象的。它接受三个参数:
ch
:一个字符数组,是新字符串的内容来源。0
:起始索引,表示从字符数组的第一个字符开始。slow
:长度,表示新字符串的长度,即从字符数组中提取的字符数量。因此,这行代码的作用是从字符数组
ch
中提取前slow
个字符,并将它们拼接成一个新的字符串对象。
import java.util.Stack;public class _1047_删除字符串中的所有相邻重复项 {public static void main(String[] args) {Solution1047 solution1047 = new Solution1047();solution1047.removeDuplicates("abbaca");}
}/*** 输入:"abbaca"* 输出:"ca"*/
class Solution1047 {public String removeDuplicates(String s) {Stack<Character> stack = new Stack<>();stack.push(s.charAt(0));for (int i = 1; i < s.length(); i++) {if (!stack.isEmpty() && stack.peek() == s.charAt(i)) {if (!stack.isEmpty()) {stack.pop();}continue;}stack.push(s.charAt(i));}
// StringBuilder sb = new StringBuilder();
// while (!stack.isEmpty()) {
// sb.append(stack.pop());
// }
// return sb.reverse().toString();String res = "";while (!stack.isEmpty()) {res += stack.pop();}return res;}}
0150_逆波兰表达式求值
1、==操作符与equals()
方法
在Java中,
==
操作符用于比较两个对象的引用是否相等,而equals()
方法用于比较两个对象的内容是否相等。具体来说:
==
操作符比较的是对象的引用,即它们是否指向内存中的同一个对象。如果两个字符串使用==
操作符比较,它们只有在指向同一个内存地址时才会返回true
,即它们是同一个对象。equals()
方法用于比较两个对象的内容是否相等。对于字符串对象,它比较的是字符串的字符序列是否相同。如果两个字符串对象的字符序列相同,则equals()
方法返回true
,否则返回false
。总的来说,使用
==
操作符来比较字符串通常不会得到预期的结果,因为它比较的是对象的引用而不是内容。因此,通常情况下我们会使用equals()
方法来比较字符串是否相等。
2、Character.isDigit(char ch)
(tokens[i].length() > 1 && tokens[i].charAt(0) == '-') 这个地方卡了很久!
这段代码是一个条件表达式,它包含两个部分,使用逻辑与操作符
&&
连接起来。
(tokens[i].length() > 1)
:这部分检查字符串的长度是否大于1。这是因为如果一个字符串只有一个字符且这个字符是负号-
,那么它不表示负数,而是一个运算符,例如-2
表示减法运算符-
和数字2
。tokens[i].charAt(0) == '-'
:这部分检查字符串的第一个字符是否是负号-
。因此,整个条件表达式检查的是输入的字符串是否表示一个负数。如果字符串的长度大于1且第一个字符是
-
,那么这个字符串就表示一个负数。
Character.isDigit(char ch)
是 Java 中的一个静态方法,用于检查给定的字符是否是一个数字字符(即 '0' 到 '9' 之间的字符)。具体来说,如果指定的字符是一个数字字符,则该方法返回
true
,否则返回false
。
import java.util.Deque;
import java.util.LinkedList;
import java.util.Stack;public class _0150_逆波兰表达式求值 {public static void main(String[] args) {Solution0150 solution0150 = new Solution0150();String[] tokens1 = {"2", "1", "+", "3", "*"};System.out.println(solution0150.evalRPN(tokens1));String[] tokens2 = {"4", "13", "5", "/", "+"};System.out.println(solution0150.evalRPN(tokens2));String[] tokens3 = {"10", "6", "9", "3", "+", "-11", "*", "/", "*", "17", "+", "5", "+"};System.out.println(solution0150.evalRPN(tokens3));}
}class Solution0150 {public int evalRPN(String[] tokens) {Stack<Integer> stack = new Stack<>();for (int i = 0; i < tokens.length; i++) {if (Character.isDigit(tokens[i].charAt(0)) || (tokens[i].length() > 1 && tokens[i].charAt(0) == '-')) {//数字stack.push(Integer.parseInt(tokens[i]));} else {//符号:+ - * /int a = stack.pop();int b = stack.pop();if (tokens[i].equals("+")) {stack.push(b + a);} else if (tokens[i].equals("*")) {stack.push(b * a);} else if (tokens[i].equals("-")) {stack.push(b - a);} else if (tokens[i].equals("/")) {stack.push(b / a);}}}return stack.pop();}
}class Solution0150_2 {public int evalRPN(String[] tokens) {Deque<Integer> stack = new LinkedList();for (String s : tokens) {if ("+".equals(s)) {//leetcode内置jdk的问题,不能使用==判断字符串是否相等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();}
}