给定一个表示数学表达式的字符串 expression,表达式由 0 到 9 的数字字符、对应的英文数字单词以及加法和减法运算符组成。数字可以使用数字字符表示,也可以使用对应的英文单词表示,例如 0 可以表示为 0 或 zero,1 可以表示为 1 或 one。表达式中的数字和运算符按照合法的数学表达式顺序排列,每两个数字之间只有一个操作符,支持的操作符只有 + 和 -。要求解析表达式并返回最终计算结果,如果输入为空、包含无法识别的数字或操作符,或者不符合规定的表达式格式,则返回 None。
示例 1:
输入:
expression = "1 + one"
输出:
2
解释:
1 表示数字 1。one 表示数字 1。+。1 + 1 = 2。示例 2:
输入:
expression = "two + zero - 1"
输出:
1
解释:
two 表示数字 2。zero 表示数字 0。1 表示数字 1。2 + 0 - 1 = 1。示例 3:
输入:
expression = "one + five - two"
输出:
4
解释:
one 表示数字 1。five 表示数字 5。two 表示数字 2。1 + 5 - 2 = 4。示例 4:
输入:
expression = "one + unknown"
输出:
None
解释:
one 是合法的数字表示。unknown 不是规定范围内的数字字符或英文数字单词。None。tokens。+ 和 -,不存在需要额外处理的运算符优先级,因此可以直接从左到右计算。None。word_to_number 映射。expression 是否为空。strip() 清理首尾空白字符。split() 将字符串拆分为 tokens。tokens 数量是否符合数字和操作符交替出现的结构。result。+,则将数字加到 result。-,则从 result 中减去数字。None。None。None。None。None。None。None。None。NumberParser。n 为输入字符串的长度。split() 产生的 tokens 计入额外空间,则空间复杂度为 O(n)。from typing import Optional
class Solution:
def evaluateExpression(self, expression: str) -> Optional[int]:
# 空字符串或者只包含空白字符的输入无法构成合法表达式。
if not expression or not expression.strip():
return None
# 建立英文数字单词到整数值的映射。
# 由于题目只允许 0 到 9,这个映射表的大小是固定的,因此不会随着输入规模增长。
word_to_number = {
"zero": 0,
"one": 1,
"two": 2,
"three": 3,
"four": 4,
"five": 5,
"six": 6,
"seven": 7,
"eight": 8,
"nine": 9
}
# 去除表达式首尾的空白字符,并按照空白字符拆分成 token。
# 例如 "two + zero - 1" 会得到 ["two", "+", "zero", "-", "1"]。
tokens = expression.strip().split()
# 合法表达式必须满足:
# 数字、操作符、数字、操作符、数字……
# 因此 token 数量必须是奇数。
if not tokens or len(tokens) % 2 == 0:
return None
def parse_number(token: str) -> Optional[int]:
# 题目允许单个数字字符 0 到 9。
# len(token) == 1 可以避免把 "123" 之类不符合题目约束的字符串当成合法数字。
if len(token) == 1 and token.isdigit():
return int(token)
# 如果不是数字字符,则尝试按照英文数字单词进行解析。
# 如果不存在对应单词,get() 会返回 None。
return word_to_number.get(token)
# 先解析第一个 token。
# 合法表达式必须以数字开始,而不能以操作符开始。
first_number = parse_number(tokens[0])
if first_number is None:
return None
# 将第一个数字作为当前计算结果。
result = first_number
# 从第 1 个 token 开始,每次处理两个 token:
# 第一个是操作符,第二个是数字。
for i in range(1, len(tokens), 2):
# 读取当前操作符。
operator = tokens[i]
# 题目只允许加法和减法。
if operator not in {"+", "-"}:
return None
# 理论上经过 token 数量检查后这里一定存在下一个数字,
# 但保留这个判断可以让代码对异常输入更加健壮。
if i + 1 >= len(tokens):
return None
# 解析操作符后面的数字。
number = parse_number(tokens[i + 1])
# 无法识别的数字直接判定为非法表达式。
if number is None:
return None
# 根据操作符更新当前结果。
if operator == "+":
result += number
else:
result -= number
# 所有 token 都成功解析并计算完成后,返回最终结果。
return result掌握同类考点的变体套路与最优解模板,举一反三快速拿下技术面试: