力扣刷题——基本计算器

227. 基本计算器 II 力扣链接

**题目要求:**给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。
整数除法仅保留整数部分。
你可以假设给定的表达式总是有效的。所有中间结果将在 [-231, 231 - 1] 的范围内。
注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。

本题是基础题,没有任何括号,相对简单一点

  • 方法1:对不同计算符号设置不用优先级,然后使用两个栈分别存储操作符和数字,进行计算
    注意:内层循环是while
class Solution {
    public int calculate(String s) {
        Map<Character,Integer> opsPrio=new HashMap<>();
        Stack<Character> ops=new Stack<>();
        Stack<Integer> number=new Stack<>();
        opsPrio.put('+', 2);
        opsPrio.put('-', 2);
        opsPrio.put('*', 3);
        opsPrio.put('/', 3);
        s=s.replace(" ","");
        for(int i=0;i<s.length();){
            char c=s.charAt(i);
            if(Character.isDigit(c)){
                int num=0;
                while(i<s.length()&&Character.isDigit(s.charAt(i))){
                    num=num*10+s.charAt(i)-'0';
                    i++;
                }
                number.push(num);
            }else{
                while(!ops.isEmpty() && opsPrio.get(c)<=opsPrio.get(ops.peek())){
                    calcul(ops,number);
                }
                ops.push(c);
                i++;
            }
        }
        while(!ops.isEmpty()){
            calcul(ops,number);
        }
        return number.peek();
    }
    private void calcul(Stack<Character> ops,Stack<Integer> number){
        if(ops.isEmpty()||number.size()<2)return;
        char c=ops.pop();
        int r=number.pop();
        int l=number.pop();
        int res=0;
        if(c=='+'){
            res=l+r;
        }else if(c=='-'){
            res=l-r;
        }else if(c=='*'){
            res=l*r;
        }else{
            res=l/r;
        }
        number.push(res);
    }
}
  • 方法2:一种基于单遍扫描的算法,使用一个栈来处理操作符和操作数。
class Solution {
    public int calculate(String s) {
        Stack<Integer> stack = new Stack<>();
        int currentNumber = 0;
        char operation = '+';
        for (int i = 0; i < s.length(); i++) {
            char currentChar = s.charAt(i);
            
            if (Character.isDigit(currentChar)) {
                currentNumber = currentNumber * 10 + (currentChar - '0');
            }
            
            if (!Character.isDigit(currentChar) && !Character.isWhitespace(currentChar) || i == s.length() - 1) {
                if (operation == '+') {
                    stack.push(currentNumber);
                } else if (operation == '-') {
                    stack.push(-currentNumber);
                } else if (operation == '*') {
                    stack.push(stack.pop() * currentNumber);
                } else if (operation == '/') {
                    stack.push(stack.pop() / currentNumber);
                }
                operation = currentChar;
                currentNumber = 0;
            }
        }
        
        int result = 0;
        while (!stack.isEmpty()) {
            result += stack.pop();
        }
        return result;
    }

224. 基本计算器 力扣链接

**题目要求:**给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。
注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。

本题是包括了()在内的题目,相对更难一些。

  • 方法:使用栈来处理操作数和操作符,并且支持括号的嵌套计算
class Solution {
    public int calculate(String s) {
        Stack<Integer> stack = new Stack<>();
        int currentNumber = 0;
        int result = 0;  // For the ongoing total
        int sign = 1;    // 1 means positive, -1 means negative
        
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            
            if (Character.isDigit(c)) {
                currentNumber = 0;
                while (i < s.length() && Character.isDigit(s.charAt(i))) {
                    currentNumber = currentNumber * 10 + (s.charAt(i) - '0');
                    i++;
                }
                result += sign * currentNumber;
                i--;  // To offset the next i++ in the for loop
            } else if (c == '+') {
                sign = 1;
            } else if (c == '-') {
                sign = -1;
            } else if (c == '(') {
                // Push the result and sign onto the stack, for later
                stack.push(result);
                stack.push(sign);
                // Reset result and sign for the new sub-expression
                result = 0;
                sign = 1;
            } else if (c == ')') {
                result = result * stack.pop() + stack.pop();
            }
        }
        
        return result;
    }
}

770. 基本计算器 IV 力扣链接

题目要求:
给定一个表达式如 expression = “e + 8 - a + 5” 和一个求值映射,如 {“e”: 1}(给定的形式为 evalvars = [“e”] 和 evalints = [1]),返回表示简化表达式的标记列表,例如 [“-1a",“14”]
表达式交替使用块和符号,每个块和符号之间有一个空格。
块要么是括号中的表达式,要么是变量,要么是非负整数。
变量是一个由小写字母组成的字符串(不包括数字)。请注意,变量可以是多个字母,并注意变量从不具有像 “2x” 或 “-x” 这样的前导系数或一元运算符 。
表达式按通常顺序进行求值:先是括号,然后求乘法,再计算加法和减法。
例如,expression = “1 + 2 * 3” 的答案是 [“7”]。
输出格式如下:
对于系数非零的每个自变量项,我们按字典排序的顺序将自变量写在一个项中。
例如,我们永远不会写像 “b
ac” 这样的项,只写 “abc”。
项的次数等于被乘的自变量的数目,并计算重复项。我们先写出答案的最大次数项,用字典顺序打破关系,此时忽略词的前导系数。
例如,"a
abc” 的次数为 4。
项的前导系数直接放在左边,用星号将它与变量分隔开(如果存在的话)。前导系数 1 仍然要打印出来。
格式良好的一个示例答案是 [“-2aaa", "3aab”, “3bb”, “4a", "5c”, “-6”] 。
系数为 0 的项(包括常数项)不包括在内。
例如,“0” 的表达式输出为 [] 。
注意:你可以假设给定的表达式均有效。所有中间结果都在区间 [-231, 231 - 1] 内。

  • 方法:使用递归下降解析来处理表达式并构建多项式表示
class Solution {
    public List<String> basicCalculatorIV(String expression, String[] evalvars, int[] evalints) {
        // Create a map for variable evaluation
        Map<String, Integer> evalMap = new HashMap<>();
        for (int i = 0; i < evalvars.length; i++) {
            evalMap.put(evalvars[i], evalints[i]);
        }
        
        // Parse the expression and return the result as a list
        return parse(expression, evalMap).toList();
    }

    private Poly parse(String expression, Map<String, Integer> evalMap) {
        Stack<Poly> stack = new Stack<>();
        Stack<Character> ops = new Stack<>();
        int n = expression.length();
        
        for (int i = 0; i < n; ) {
            char c = expression.charAt(i);
            if (c == ' ') {
                i++;
            } else if (c == '(') {
                ops.push(c);
                i++;
            } else if (c == ')') {
                while (ops.peek() != '(') {
                    stack.push(applyOp(stack.pop(), stack.pop(), ops.pop()));
                }
                ops.pop();
                i++;
            } else if (Character.isDigit(c) || Character.isLetter(c)) {
                int j = i;
                while (j < n && (Character.isDigit(expression.charAt(j)) || Character.isLetter(expression.charAt(j)))) {
                    j++;
                }
                String term = expression.substring(i, j);
                i = j;
                if (Character.isDigit(term.charAt(0))) {
                    stack.push(new Poly(Integer.parseInt(term)));
                } else {
                    if (evalMap.containsKey(term)) {
                        stack.push(new Poly(evalMap.get(term)));
                    } else {
                        stack.push(new Poly(term, 1));
                    }
                }
            } else if (c == '+' || c == '-' || c == '*') {
                while (!ops.isEmpty() && precedence(ops.peek()) >= precedence(c)) {
                    stack.push(applyOp(stack.pop(), stack.pop(), ops.pop()));
                }
                ops.push(c);
                i++;
            }
        }
        
        while (!ops.isEmpty()) {
            stack.push(applyOp(stack.pop(), stack.pop(), ops.pop()));
        }
        return stack.pop();
    }

    private int precedence(char op) {
        if (op == '+' || op == '-') return 1;
        if (op == '*') return 2;
        return 0;
    }

    private Poly applyOp(Poly b, Poly a, char op) {
        if (op == '+') return a.add(b);
        if (op == '-') return a.subtract(b);
        if (op == '*') return a.multiply(b);
        return new Poly();
    }

    class Poly {
        Map<List<String>, Integer> terms;

        Poly() {
            terms = new HashMap<>();
        }

        Poly(int coeff) {
            terms = new HashMap<>();
            if (coeff != 0) {
                terms.put(new ArrayList<>(), coeff);
            }
        }

        Poly(String var, int coeff) {
            terms = new HashMap<>();
            if (coeff != 0) {
                terms.put(new ArrayList<>(Arrays.asList(var)), coeff);
            }
        }

        Poly add(Poly other) {
            Poly res = new Poly();
            for (List<String> key : this.terms.keySet()) {
                res.terms.put(key, this.terms.getOrDefault(key, 0) + other.terms.getOrDefault(key, 0));
            }
            for (List<String> key : other.terms.keySet()) {
                if (!this.terms.containsKey(key)) {
                    res.terms.put(key, other.terms.get(key));
                }
            }
            return res;
        }

        Poly subtract(Poly other) {
            Poly res = new Poly();
            for (List<String> key : this.terms.keySet()) {
                res.terms.put(key, this.terms.getOrDefault(key, 0) - other.terms.getOrDefault(key, 0));
            }
            for (List<String> key : other.terms.keySet()) {
                if (!this.terms.containsKey(key)) {
                    res.terms.put(key, -other.terms.get(key));
                }
            }
            return res;
        }

        Poly multiply(Poly other) {
            Poly res = new Poly();
            for (List<String> key1 : this.terms.keySet()) {
                for (List<String> key2 : other.terms.keySet()) {
                    List<String> key = new ArrayList<>(key1);
                    key.addAll(key2);
                    Collections.sort(key);
                    int coeff = this.terms.get(key1) * other.terms.get(key2);
                    res.terms.put(key, res.terms.getOrDefault(key, 0) + coeff);
                }
            }
            return res;
        }

        List<String> toList() {
            List<String> res = new ArrayList<>();
            List<List<String>> keys = new ArrayList<>(terms.keySet());
            Collections.sort(keys, (a, b) -> {
                if (a.size() != b.size()) return b.size() - a.size();
                return a.toString().compareTo(b.toString());
            });
            for (List<String> key : keys) {
                int coeff = terms.get(key);
                if (coeff == 0) continue;
                StringBuilder sb = new StringBuilder();
                sb.append(coeff);
                for (String var : key) {
                    sb.append('*').append(var);
                }
                res.add(sb.toString());
            }
            return res;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值