首页 > 其他分享 >23-05-26 刷题-【中缀表达式求值的模板】

23-05-26 刷题-【中缀表达式求值的模板】

时间:2023-05-26 19:12:30浏览次数:57  
标签:numStack 26 ch opStack 中缀 int else num 求值

basic calculator系列题目:(可以作为模板题,记住)

224. 基本计算器 - 力扣(LeetCode) [hard]

想法:

  • 中缀表达式求值。数据结构中栈的应用

    • 中缀转后缀。后缀能去掉括号。a + (b + c)*d ==》 abc+d*+
    • 后缀表达式求值: abc+d*+
    • 要考虑表达式的优先级,怎么处理括号。 括号的优先级,不知道怎么处理。
    • 处理特殊情况: 1 + (-2)这种情况
  • 总结1:这题处理特例1-( -2)太恶心了。

  • 总结2:对于运算符和符号,分两类,运算符有优先级,左右括号特殊处理一下。

  • 代码技巧1:evaluate函数,直接传入两个stack,然后计算一次。不加返回值。这种写法比传入numStack和opCode,然后返回计算结果好。因为后者还需要在调用处,把结果push到栈里。

  • 代码技巧2:parse 数字时,使用循环直接解析,而不要重用外层的循环。这样更清晰一点。

class Solution {
    public int calculate(String s) {
        Deque<Integer> numStack = new ArrayDeque<>(); // 存操作数的栈
        Deque<Character> opStack = new ArrayDeque<>(); // 存运算符的栈
        // 原则:能算就算
        // 将运算符+-*/ 和 ()分成两类。运算符定义优先级,括号特殊处理
        int prev = -1;
        for(int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            if (ch == ' ') continue;
            else if (Character.isDigit(ch)) {
                // parse the number use a loop
                int j = i, num = 0;
                for (; j < s.length() && Character.isDigit(s.charAt(j)); j++) {
                    num = num * 10 + (s.charAt(j) - '0');
                }
                numStack.push(num);
                i = j - 1;
            } else { // operation code
                if (ch == '(') { //压栈
                    opStack.push(ch);
                } else if (ch == ')') {
                    while (opStack.peek() != '(') {
                        // evaluate the stack
                        evaluate(numStack, opStack);
                    }
                    opStack.pop();
                } else {
                    if (prev == -1 || s.charAt(prev) == '+' || s.charAt(prev) == '-' || s.charAt(prev) == '(') {
                        numStack.push(0);
                    }
                    // 因为只有+-,优先级一样,不需要比较优先级了
                    while (!opStack.isEmpty() && opStack.peek() != '(') {
                        evaluate(numStack, opStack);
                    }
                    opStack.push(ch);
                }
            }
            prev = i;
        }       
        while (!opStack.isEmpty()) {
            evaluate(numStack, opStack);
        }
        return numStack.pop();
    }

    void evaluate(Deque<Integer> numStack, Deque<Character> opStack) {
        int b = numStack.pop();
        int a = 0;
        if (!numStack.isEmpty())
            a = numStack.pop();
        char opCode = opStack.pop();
        if (opCode == '+') {
            numStack.push(a + b);
        } else if (opCode == '-') {
            numStack.push(a - b);
        }
    }
}

复杂度分析:

  • 时间:O(n), 字符串遍历一遍,最多有n个元素入栈和出栈, 空间O(n)

官方答案的解法:

227. 基本计算器 II - 力扣(LeetCode) 【mid】

直接套用上面的模板,修改下优先级即可。这题没有括号,也没有单目运算符,所以是mid级别,不是很难。

class Solution {
    public int calculate(String s) {
        Deque<Integer> numStack = new ArrayDeque<>();
        Deque<Character> opStack = new ArrayDeque<>();

        for(int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            if (ch == ' ') continue;
            if (Character.isDigit(ch)) {
                int num = 0, j = i;
                for(; j < s.length() && Character.isDigit(s.charAt(j)); j++) {
                    num = num * 10 + (s.charAt(j) - '0');
                }
                numStack.push(num);
                i = j - 1;
            } else {
                while (!opStack.isEmpty() && getPriority(ch) <= getPriority(opStack.peek())) {
                    evaluate(numStack, opStack);
                }
                opStack.push(ch);
            }
        }
        while (!opStack.isEmpty()) {
            evaluate(numStack, opStack);
        }
        return numStack.peek();
    }

    void evaluate(Deque<Integer> numStack, Deque<Character> opStack) {
        int a = numStack.pop(), b = numStack.pop();
        char op = opStack.pop();
        int res = 0;
        if (op == '+') res = b + a;
        else if (op == '-') res = b - a;
        else if (op == '*') res = b * a;
        else if (op == '/') res = b / a;
        numStack.push(res);
    }

    int getPriority(char ch) {
        if (ch == '+' || ch == '-') return 1;
        if (ch == '*' || ch == '/') return 2;
        return 0;
    }
}

/*
思路:
1. 中缀表达式求值,使用两个stack,一个numStack, 一个opStack
2. 原则,能算则算。 a + b + c   --》 先计算a+b, 然后入栈
   a+b*c 不能先算a+b 因此,当后面*优先级高于栈顶时,直接入栈。
   操作数直接入栈。
   操作符: 如果当前操作符比栈顶高,入栈。否则,先计算栈顶。
   当表达式遍历完成,再处理opStack,每次取出一个op,然后从numStack取出两个数计算,将结果压到numStack中
   最后结果是numStack的栈顶元素
 */

772. 基本计算器 III - 力扣(LeetCode) 【hard】

  • 使用上面的模板。同样这题没有空格,也没有恶心的单目运算符,所以还好。
class Solution {
    public int calculate(String s) {
        Deque<Integer> numStack = new ArrayDeque<>();
        Deque<Character> opStack = new ArrayDeque<>();

        for(int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            if (ch == ' ') continue;
            if (Character.isDigit(ch)) {
                int num = 0, j = i;
                for(; j < s.length() && Character.isDigit(s.charAt(j)); j++) {
                    num = num * 10 + (s.charAt(j) - '0');
                }
                numStack.push(num);
                i = j - 1;
            } else {
                if (ch == '(') {
                    opStack.push(ch);
                } else if (ch == ')') {
                    while (opStack.peek() != '(') {
                        evaluate(numStack, opStack);
                    }
                    opStack.pop();
                } else {
                    while (!opStack.isEmpty() && opStack.peek() != '(' && getPriority(ch) <= getPriority(opStack.peek())) {
                        evaluate(numStack, opStack);
                    }
                    opStack.push(ch);
                }
            }
        }
        while (!opStack.isEmpty()) {
            evaluate(numStack, opStack);
        }
        return numStack.peek();
    }

    void evaluate(Deque<Integer> numStack, Deque<Character> opStack) {
        int a = numStack.pop(), b = numStack.pop();
        char op = opStack.pop();
        int res = 0;
        if (op == '+') res = b + a;
        else if (op == '-') res = b - a;
        else if (op == '*') res = b * a;
        else if (op == '/') res = b / a;
        numStack.push(res);
    }

    int getPriority(char ch) {
        if (ch == '+' || ch == '-') return 1;
        if (ch == '*' || ch == '/') return 2;
        return 0;
    }
}

770. 基本计算器 IV - 力扣(LeetCode) [hard]

这个有变量,似乎跟前面不太一样,很难。TODO。

标签:numStack,26,ch,opStack,中缀,int,else,num,求值
From: https://www.cnblogs.com/xianzhon/p/17435606.html

相关文章

  • 2023.5.26——软件工程日报
    所花时间(包括上课):6h代码量(行):0行博客量(篇):1篇今天,上午学习,下午学习。我了解到的知识点:1.了解了一些数据库的知识;2.了解了一些python的知识;3.了解了一些英语知识;5.了解了一些Javaweb的知识;4.了解了一些数学建模的知识;6.了解了一些计算机网络的知识;......
  • 2023.5.26——软件工程站立会议(阶段二)
    站立会议内容:1.整个项目预期的任务量:目前已经花的时间:剩余的时间:2.任务看板照片: 3.团队照片: 4.产品状态:最新做好的功能:正在完成中5.燃尽图:......
  • 5.26打卡
    #include<bits/stdc++.h>usingnamespacestd;classExamInfo{public:ExamInfo(stringname,chargrade):name(name),mode(GRADE),grade(grade){}ExamInfo(stringname,boolpass):name(name),mode(PASS),pass(pass){}ExamInfo(strin......
  • 5月26日总结
    ArcMap手动新建矢量要素的方式合集-GIS空间分析(7)1.地统计学的基本概念及公式详解04-242.单窗算法的地表温度反演:谷歌地球引擎GEE代码04-263.SPSS计算极值、平均值、中位数、方差、偏度、峰度、变异系数05-084.Python忽略NoData计算多张遥感影像的像元平均值:whitebox库......
  • 2023.5.26编程一小时打卡
    一、问题描述:定义复数类MyComplex,主函数完成相关测试。MyComplex类结构说明:1、数据成员包括:私有数据成员:实部x(double)虚部y(double)。2、成员函数包括:无参构造函数MyComplex(void),其功能是将数据成员数部和虚部的值均设为0;有参构造函数MyComplex(doublevalue1,doublevalue2),其功能......
  • 5.26打卡
      3.程序流程图4.代码实现 #include<bits/stdc++.h>usingnamespacestd;main(){inti,j,s,n;printf("请输入所选范围上限:");scanf("%d",&n);for(i=2;i<=1000;i++){s=0;for(j=1;j<=n/2;j++)......
  • C++外卖点餐系统[2023-05-26]
    C++外卖点餐系统[2023-05-26]选题九:外卖点餐系统7.基本要求:[1]编写一个外卖点餐系统,实现对客户、店铺、订单及配送人员等信息的管理。[2]客户信息包括:客户姓名、联系方式、地址等;店铺信息包括:其菜品和价格评分等;配送人员信息包括:姓名,联系方式、评分等:订单信息包括:编......
  • 2023/5/26
    函数模板实现两个数之间的距离重点:复数类#include<iostream>#include<bits/stdc++.h>usingnamespacestd;template<classT>doubledist(Ta,Tb){returna-b;}classComplex{private:doublereal,imag;public:Complex......
  • 5.26上课用java代码
    packagexu01;importjava.io.*;publicclasscaishu{publicstaticvoidmain(Stringargs[])throwsIOException{ booleanagain=false; loop1:do{ inttrueNum=(int)(Math.random()*9); System.out.println("游戏开始了"); inti=3; do{ System.out.println......
  • 2023.5.26 Linux系统基础命令
    系统⽬录结构⽂件路径定位⽬录管理命令⽂件管理命令⽂件查看命令⽂件下载命令命令查找命令字符处理命令练习如下命令系统⽬录结构⼏乎所有的计算机操作系统都是⽤⽬录结构组织⽂件。具体来说就是在⼀个⽬录中存放⼦⽬录和⽂件,⽽在⼦⽬录中⼜会进⼀步存放⼦⽬录和⽂件,以此类推形......