给定一个类似 Lisp 语句的表达式 expression,求出其计算结果。
表达式语法如下所示:
- 表达式可以为整数,let 语法,add 语法,mult 语法。表达式的结果总是一个整数。(整数可以是正整数、负整数、0)
- let 语法表示为 (let v1 e1 v2 e2 … vn en expr), 其中 let语法总是以字符串
"let"来表示,接下来会跟随一个或多个交替变量或表达式,也就是说,第一个变量 v1被分配为表达式 e1 的值,第二个变量 v2
被分配为表达式 e2 的值,以此类推;最终 let 语法的值为 expr表达式的值。 - add语法表示为 (add e1 e2),其中 add 语法总是以字符串 "add"来表示,该语法总是有两个表达式e1、e2,
该语法的最终结果是 e1 表达式的值与 e2 表达式的值之和。 - mult语法表示为 (mult e1 e2) ,其中 mult 语法总是以字符串"mult"表示, 该语法总是有两个表达式
e1、e2,该语法的最终结果是 e1 表达式的值与 e2 表达式的值之积。 - 在该题目中,变量的命名以小写字符开始,之后跟随0个或多个小写字符或数字。为了方便,“add”,“let”,“mult"会被定义为"关键字”,不会在表达式的变量命名中出现。
最后,要说一下范围的概念。在做计算时,需要注意优先级,在最内层(根据括号)的表达式的值应该先计算,然后依次计算外层的表达式。我们将保证每一个测试的表达式都是合法的。有关范围的更多详细信息,请参阅示例。
示例:
输入: (add 1 2)
输出: 3
输入: (mult 3 (add 2 3))
输出: 15
输入: (let x 2 (mult x 5))
输出: 10
输入: (let x 2 (mult x (let x 3 y 4 (add x y))))
输出: 14
解释:
表达式 (add x y), 在获取 x 值时, 我们应当由最内层依次向外计算, 首先遇到了 x=3, 所以此处的 x 值是 3.
输入: (let x 3 x 2 x)
输出: 2
解释: let 语句中的赋值运算按顺序处理即可
输入: (let x 1 y 2 x (add x y) (add x y))
输出: 5
解释:
第一个 (add x y) 计算结果是 3,并且将此值赋给了 x 。
第二个 (add x y) 计算结果就是 3+2 = 5 。
输入: (let x 2 (add (let x 3 (let x 4 x)) x))
输出: 6
解释:
(let x 4 x) 中的 x 的作用范围仅在()之内。所以最终做加法操作时,x 的值是 2 。
输入: (let a1 3 b2 (add a1 1) b2)
输出: 4
解释:
变量命名时可以在第一个小写字母后跟随数字.
注意:
我们给定的 expression 表达式都是格式化后的:表达式前后没有多余的空格,表达式的不同部分(关键字、变量、表达式)之间仅使用一个空格分割,并且在相邻括号之间也没有空格。我们给定的表达式均为合法的且最终结果为整数。
我们给定的表达式长度最多为 2000 (表达式也不会为空,因为那不是一个合法的表达式)。
最终的结果和中间的计算结果都将是一个 32 位整数。
思路分析: 这道题是典型的字符串细节处理问题,我们只要抓住每次处理一个"(…)",这个expression是会得到一个值,而只有add、mult、let三种操作。
首先介绍表达式的可能情况:
第一种:表达式是"(...)",按照三种基本操作递归处理得到表达式的值。
第二种:表达式是变量,直接返回变量对应的值,比如(let x 2 (add x 5)),let中赋值x = 2,则add(x, y)第一个参数表达式的值x = 2
第二种:表达式是常量,直接返回常量的值,比如(add 3 5),l则add(x, y)两个参数表达式都是常量x = 2, y = 3
下面是三种基本操作:
第一种:(add e1 e2),处理add,我们先处理e1、e2两个表达式,得到e1、e2两个表达式的值,进行加法计算,得到当前expression的值
第二种:(mult e1 e2),处理mult,我们先处理e1、e2两个表达式,得到e1、e2两个表达式的值,进行乘法法计算,得到当前expression的值。
第三种:(let v1 e1 v2 e2 ... vn en expr),对于(v1 e1),(v2,e2),(v3,e3), ... , (v n - 1,e n - 1),(v n,e n)这都是赋值操作,对于e1到en共n个表达式,我们分别求出这n个表达式的值,然后赋值到n个变量v1到vn即可,最后求出表达式expr的值就是当前expression的值。
class Solution {
public:
int evaluate(string expression) {
int nowIndex = 1;//即将处理的字符串下标,初始化为1,因为每个输入都有一个外加括号
unordered_map<string, int> hashMap;//用于储存这个表达式中let赋值操作
return myEvaluate(expression, nowIndex, hashMap);//开始处理一个expression
}
//开始处理以nowIndex为起始的一个expression
int myEvaluate(string &expression, int &nowIndex, unordered_map<string, int> hashMap){
if (expression[nowIndex] == 'a'