题解 | #表达式求值#
表达式求值
http://www.nowcoder.com/practice/c215ba61c8b1443b996351df929dc4d4
经典的中缀表达式求值。常用思路,将其转为后缀表达式,边转边求值。
后缀表达式的特点,遇到运算符则将前两个数拿出来运算,便于计算机计算。
这里简单描述一下算法过程:遍历字符串,当读到的是数字时,直接将其压入数字栈。当读到的是运算符时,若符号栈为空,则直接将其压入符号栈;若符号栈非空,则判断符号栈栈顶的运算符优先级,若其优先级大于等于读到的优先级,则将其出栈,并从数字栈弹出两个元素进行该运算,先弹出的为右操作数,后弹出的为左操作数,将结果压入数字栈。重复该操作,直到符号栈栈顶运算符的优先级小于读取的运算符,或符号栈空,则将读取的运算符压入符号栈。重复以上操作直到字符串读完。最后,若符号栈非空,则弹出栈顶元素,并从数字栈弹出两个元素来进行该运算。重复该操作直到符号栈空。弹出数字栈栈顶元素,即得结果。
注:本题中运算符优先级:')'<'+'='-'<'*'。左括号'('较为特殊,读到左括号时直接入栈,读到右括号时一直出栈直到一个左括号出栈。
最初遇到两个坑。一个是在判断运算符出栈条件时,优先级相等的运算符未出栈。这样就造成中缀表达式变为右结合,当算式运算中一直大于等于0时不会出现问题,而当其中出现负数减法时就会出错。如1-2-3,正常情况下左结合结果为-4,而右结合得到的结果时2。另一个坑是在遍历字符串数组时,最开始惯性思维默认了表达式中数字都是个位数,所以循环中每次仅读入1个字符。而提交的用例中有100+100的例子,这样数字栈就变成了先压入1,再压入0...最后改写了读入数据的逻辑,美中不足的是这样做会在循环体内改变循环控制变量i,容易出错。
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* 返回表达式的值
* @param s string字符串 待计算的表达式
* @return int整型
*/
int solve(string s) {
// write code here
stack<char> sign;
stack<int> num;
for(int i = 0;i<s.length();i++){
if(s[i] >= '0' && s[i] <= '9'){
int rear = i;
while((rear+1)<s.length() && s[rear+1] >= '0' && s[rear+1] <= '9'){
rear++;
}
int n = 0;
for(int j=rear;j>=i;j--){
n += (s[j]-'0')*pow(10,(rear-j));
}
i = rear;
num.push(n);
}
else if(sign.size() == 0 || s[i] == '*'|| s[i] == '('){
sign.push(s[i]);
}
else if(s[i] == '+' || s[i] == '-'){
while(1){
if(sign.size() == 0){
break;
}
if(sign.top() == '*'){
sign.pop();
int n2 = num.top();
num.pop();
int n1 = num.top();
num.pop();
num.push(n1*n2);
}
else if(sign.top() == '+'){
sign.pop();
int n2 = num.top();
num.pop();
int n1 = num.top();
num.pop();
num.push(n1+n2);
}
else if(sign.top() == '-'){
sign.pop();
int n2 = num.top();
num.pop();
int n1 = num.top();
num.pop();
num.push(n1-n2);
}
else{
break;
}
}
sign.push(s[i]);
}
else if(s[i] == ')'){
while(1){
if(sign.size() == 0){
break;
}
else if(sign.top() == '('){
sign.pop();
break;
}
else if(sign.top() == '+'){
sign.pop();
int n2 = num.top();
num.pop();
int n1 = num.top();
num.pop();
num.push(n1+n2);
}
else if(sign.top() == '-'){
sign.pop();
int n2 = num.top();
num.pop();
int n1 = num.top();
num.pop();
num.push(n1-n2);
}
else if(sign.top() == '*'){
sign.pop();
int n2 = num.top();
num.pop();
int n1 = num.top();
num.pop();
num.push(n1*n2);
}
}
}
}
while(sign.size()!=0){
if(sign.top() == '+'){
sign.pop();
int n2 = num.top();
num.pop();
int n1 = num.top();
num.pop();
num.push(n1+n2);
}
else if(sign.top() == '-'){
sign.pop();
int n2 = num.top();
num.pop();
int n1 = num.top();
num.pop();
num.push(n1-n2);
}
else if(sign.top() == '*'){
sign.pop();
int n2 = num.top();
num.pop();
int n1 = num.top();
num.pop();
num.push(n1*n2);
}
}
return num.top();
}
}; 

海康威视公司福利 1125人发布