[路飞]_基本计算器

226 阅读1分钟

题目介绍

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。

示例1

输入: s = "1 + 1"
输出: 2

示例2

输入: s = " 2-1 + 2 "
输出: 3

示例3

输入: s = "(1+(4+5+2)-3)+(6+8)"
输出: 23

提示:

解题思路

本题由于有括号参与计算,根据小学知识

如果是顺序计算,如果括号前面的符号是 '-',那么括号中的运算需要改变,如果括号前面的符号是 '+',则括号中的运算不需要改变

如果按运算符的优先级计算,那么应该先执行括号中计算,然后再执行括号外的计算

本文将基于这两种思想,提出两种解决办法

思路一:顺序计算

顺序计算的目的是消掉算式中的括号,需要考虑括号前面的符号,因此,当遇到 '(' 时,将 '(' 前面的符号压入栈中,遇到 ')' 时,将栈顶符号弹出

如果 '(' 前面是 '+',那么括号中的 '+' 按 '+' 计算,'-' 按 '-' 计算
如果 '(' 前面是 '-',那么括号中的 '+' 按 '-' 计算,'+' 按 '-' 计算

由此可得出一般规律,遇到 '-' 时,取栈顶符号的相反符号进行计算,遇到 '+' 时,取栈顶符号进行计算

1.gif

解题代码

var calculate = function(s) {
    // 定义一个符号栈
    const sign = [1]
    // 定义sum用于保存计算结果,op为当前的运算符,n用于将string类型的数字转化成number类型
    let sum = 0, op = 1, n = 0
    for (let i = 0; i < s.length; i++) {
        // 如果遇到' ',直接跳过
        if (s[i] === ' ') continue
        // 如果遇到数字,将string转成number
        if (s[i] - '0' >= 0 && s[i] - '0' <= 9) {
            n = n * 10 + s[i] * 1
            continue
        }
        // 当遇到数字和空格以外的符号,当前数字参与计算
        sum += op * n
        n = 0
        // 如果遇到'-',符号位为栈顶取反
        if (s[i] === '-') op = -sign[sign.length - 1]
        // 如果遇到'+', 符号位为栈顶值
        if (s[i] === '+') op = sign[sign.length - 1]
        // 如果遇到'(',将当前的符号位压入栈顶
        if (s[i] === '(') sign.push(op)
        // 如果遇到')',弹出栈顶的符号位
        if (s[i] === ')') sign.pop()
    }
    // 将最后一个值参与运算 
    sum += op * n
    return sum
};

思路二:双栈法(按运算优先级)

按运算符优先级计算时,我们需要先计算括号内的,再计算括号外的,但是同一层括号的运算可以从左到右进行计算

1640709089(1).png
因此,当没有遇到括号时,从左往右进行计算,当遇到 '(' 时,需要将当前的计算结果和符号先压入栈中,然后计算括号中的式子,当遇到 ')' 时,将数字栈和符号栈中的元素依次弹出进行计算

2.gif

解题代码

var calculate = function(s) {
    // 定义数字栈,符号栈用于保存数字和符号
    const nums = [], opts = []
    // 定义sum用于保存阶段性的和,定义n用于将每个参与计算的数从string转为number,定义sign表示符号位
    let sum = 0, n = 0, sign = 1
    for (let i = 0; i < s.length; i++) {
        // 跳过s中的' '
        if (s[i] === ' ') continue
        // 遇到数字时,将string类型的数字转成number
        if (s[i] - '0' >= 0 && s[i] - '0' <= 9) {
            n = n * 10 + s[i] * 1
            while (s[i + 1] !== ' ' && s[i + 1] - '0' >= 0 && s[i + 1] - '0' <= 9) {
                i++
                n = n * 10 + s[i] * 1
            }
            // 将该值进行计算
            sum += sign * n
            n = 0
        }
        // 遇到'+' 或 '-',修改 sign 符号位
        if (s[i] === '+' || s[i] === '-') sign = s[i] === '+' ? 1 : -1
        // 如果遇到 '(',说明接下来要计算括号中的内容,将括号外的内容先存起来
        if (s[i] === '(') {
            nums.push(sum)
            sum = 0
            opts.push(sign)
            sign = 1
        }
        // 如果遇到 ')',说明括号中的内容计算完毕,将前面保存的值弹出计算
        if (s[i] === ')') {
            sum = nums.pop() + opts.pop() * sum
        }
    }
    return sum
};

以上就是本题的解答过程,如果大家有什么意见或建议,欢迎留言