day_11
传送门
-
20 - 有效的括号 - 题目链接/文章讲解/视频讲解
-
1047 - 删除字符串中的所有相邻重复项 - 题目链接/文章讲解/视频讲解
-
150 - 逆波兰表达式求值 - 题目链接/文章讲解/视频讲解
20 - 有效的括号
- 思路:栈处理,因为这个也算是相邻字符的消除
- 遍历字符串
- 遇到左括号入栈,入栈的时候将左括号转为对应的右括号
- 遇到右括号,与栈顶比较,
- 不等就直接 return,因为左右括号不匹配 (左右括号不匹配的情况)
- 相等的话,就直接 pop 栈顶
- 如果没遍历完,就发现栈已经空了,也 return 掉 (右括号多了)
- 遍历结束后,可能会有左括号剩余,栈会不为空,返回 stack.isEmpty (左括号多了)
- 遍历字符串
class Solution {
public static boolean isValid(String s) {
Deque<Character> stack = new ArrayDeque<>(); // 双端队列(数组型 + 链表型)
for (char ch : s.toCharArray()) {
// push 左括号
if (pushLeft(stack, ch));
// 遇到右括号,开始判断并 pop,
else if (stack.isEmpty() || stack.peek()!= ch) return false;
else stack.pop();
}
return stack.isEmpty();
}
public static boolean pushLeft(Deque<Character> deque, char ch){
switch (ch){
case '(' :
deque.push(')');
return true;
case '[' :
deque.push(']');
return true;
case '{' :
deque.push('}');
return true;
default:
return false;
}
}
}
- 丑陋的C代码实现
// /* 20 有效的括号 */
// #include <stdbool.h>
#define SIZE 5000
// 处理每一个遇到的字符串,把左括号变为右括号
char changeCharecter(char* s, int i){
switch (s[i])
{
case '(':
return ')' ;
break;
case '[':
return ']' ;
break;
case '{':
return '}' ;
break;
default:
return s[i];
break;
}
}
typedef struct{
char stack[SIZE];
int size;
}Stack;
bool isValid(char * s){
// 初始化栈,其实可以更直接一点,用数组模拟栈的
Stack* stack = (Stack* )malloc(sizeof(Stack));
stack->size = 0;
// 开始遍历字符串
int sizeStr = strlen(s);
for (int i = 0; i < sizeStr; i++){
char curCh = s[i]; // 当前字符
char changedCurCh = changeCharecter(s, i); // 处理后的当前字符
// push 操作,只有左括号才 push 进来
if (curCh == '(' || curCh == '{' || curCh == '[') {
int index = stack->size;
stack->stack[index] = changedCurCh;
stack->size = index + 1;
continue;
}
// 遇到右括号后,开始 pop 操作
if (stack -> size > 0){
int size = stack -> size;
char top = stack -> stack[size - 1]; // 取栈顶元素
if (top == curCh){ // 如果栈顶和当前右括号相同,pop
stack -> size = size - 1;
continue;
}
else {
return false; // 这是括号不匹配的情况
}
}
if (stack -> size <= 0) return false;
}
return stack -> size <= 0;
}
1047 - 删除字符串中的所有相邻重复项
-
栈的方式处理
- 处理前后相邻的元素问题很容易用栈方式进行实现
- 遍历到的不重复的字符添加到栈里,重复的 pop掉
- 最后的栈里就只剩下不重复的字符了
-
java使用栈的实现
class Solution {
public String removeDuplicates(String s) {
StringBuilder sb = new StringBuilder(); // 用字符串模拟栈
for (char ch : s.toCharArray()) { // 开始遍历字符串
int resIndex = sb.length()-1; // 结果里的下标
if (sb.length() == 0 || ch != sb.charAt(resIndex)){ // 如果栈为空或前后字母不相等,就把当前的字符添加进来
sb.append(ch);
}
else if(ch == sb.charAt(resIndex)){ // 如果栈顶与ch相同,就pop
sb.deleteCharAt(resIndex);
}
}
return sb.toString();
}
}
- C语言双指针实现,将字符串直接当作栈来使用
// 将整个字符串当作栈来使用了,slow指向栈顶,slow--相当于pop操作
// 当栈空了(slow < 0) 或者 栈顶和当前对比的字符不同时(s[slow] != s[fast]) 就将当前字符入栈 s[++slow] = s[fast]
// 发现当前对比的字符与栈顶相同时,对栈进行 pop 操作!
char *removeDuplicates(char *s){
int fast = 1; // 快指针可以不用从 0 开始的
int slow = 0;
int size = strlen(s);
for ( ; fast < size; fast++){ // 遍历整个字符串
if (slow < 0 || s[slow] != s[fast]){ // 遇到需要修改字符的情况
s[++slow] = s[fast]; // push
}
else{
slow--; // pop
}
}
s[++slow] = '\0';
return s;
}
150 - 逆波兰表达式求值
-
栈在计算机里的经典应用
- 遇到数字入栈
- 遇到符号的话,出栈两个数字,进行运算后,再将结果放回栈里
- 如此循环,直至结束
-
java实现,注意点: leetcode 内置jdk的问题,不能使用==判断字符串是否相等
-
每次的操作都是 secondPop op firstPop
-
似乎直接写 if 更简洁一些
class Solution {
public int evalRPN(String[] tokens) {
Deque<Integer> nums = new LinkedList<>();
for (String s : tokens) { // 遍历字符串数组
// 先判断该符号是什么
if (s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/") ){ // 遇到符号,pop两数,求解后push回去
Integer a = nums.pop();
Integer b = nums.pop();
nums.push(getRes(a, b, s));
continue;
}
Integer num = Integer.valueOf(s);
nums.push(num);
}
return nums.peek();
}
public Integer getRes(Integer firstPop , Integer secondPop, String s){
switch (s){
case "+":
return firstPop+secondPop;
case "-":
return secondPop - firstPop;
case "*":
return firstPop*secondPop;
case "/":
return secondPop / firstPop;
default:
return null;
}
}
}