SWE · Coding

Meta 计算器:加乘优先级与右结合幂

解析非负整数的加法、乘法和幂,合并只含加乘的简化版本并明确语法。

题目重点:解析非负整数的加法、乘法和幂,合并只含加乘的简化版本并明确语法。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练ASCII非负整数、+ * ^、空白,优先级^>* >+,^右结合,0^0=1;不含括号/一元符号/减除。加乘版只用此语法子集。
  • power字面运算符与结合性未明确,因此当前^和右结合是训练约定,实际接口需确认。

解题路线

  1. 递归下降expr=term(+term)*,term=power(*power)*,power=number(^power)?。加乘循环左结合,power递归右侧形成右结合。
  2. number逐ASCII digit构整数,允许token间空白但不能直接去掉所有空白再拼字符串:1 2是两个不合法相邻操作数,不应变12。
  3. term完整计算乘法再交expr加法,自然实现优先级;5+2*4得13,不用逐左算成28。^调用自身让2^3^2是2^(3^2)。
  4. 解析结束必须消耗全文,非法字符/缺operand报错;不得eval用户输入。测试仅对程序生成可信表达式用独立Python算术oracle。
  5. 幂可制造很大整数,未给约束不能声称无穷可安全计算;语法复杂度与结果位数分开,长幂链有递归深度风险。

手动走一遍

5+2*4=13;2^3^2=512而(2^3)^2=64;1 2、1+、−1、括号都不属本合同应拒绝。幂符号^在Python是XOR,但本解析器把它定义为幂。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

def calculate(text):
    """Training: nonnegative ASCII integer operands, + * ^, whitespace.
    No parentheses, unary signs, subtraction or division.
    Precedence ^ > * > +; ^ right associative; 0^0=1.
    """
    index=0
    def skip():
        nonlocal index
        while index<len(text) and text[index].isspace():index+=1
    def number():
        nonlocal index
        skip();start=index;value=0
        while index<len(text) and '0'<=text[index]<='9':
            value=value*10+ord(text[index])-ord('0');index+=1
        if index==start:raise ValueError('integer operand expected')
        return value
    def power():
        nonlocal index
        value=number();skip()
        if index<len(text) and text[index]=='^':
            index+=1;value=value**power()
        return value
    def term():
        nonlocal index
        value=power();skip()
        while index<len(text) and text[index]=='*':
            index+=1;value*=power();skip()
        return value
    result=term();skip()
    while index<len(text) and text[index]=='+':
        index+=1;result+=term();skip()
    if index!=len(text):raise ValueError('unexpected token')
    return result

复杂度

O(T)token解析工作,加大整数乘法/幂的实际位复杂度;递归stack O(幂链长度)。若只+/*,可用累计term的O(1)语法状态,但当前幂扩展不能直接标常数辅助。

易错点与追问

容易失分的边界

  • 去掉全部空白把非法相邻数字拼成合法数。
  • 幂左结合改变结果。
  • Python ^当幂调用会实际执行XOR。

继续深挖

  • 增加括号时number层可扩成primary,但需要匹配闭括号和深度预算。
  • 如何限制指数/结果位数保护资源?错误应在接口合同中明确。
✓已复制微信号!