代码随想录算法训练营第十一天 | 20. 有效的括号、1047. 删除字符串中的所有相邻重复项、150. 逆波兰表达式求值

本文介绍了如何使用栈数据结构解决编程问题,包括检查有效括号的匹配、删除字符串中相邻重复字符以及逆波兰表达式的求值。通过栈的入栈和出栈操作,展示了算法的核心思路和C、Java代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

day_11

传送门


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;
        }
    }

    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值