【题目】
给定一个字符串str,str表示一个公式,公式里可能有整数,加减乘除符号和左右括号,返回公式计算的结果。例如,str = 48×((70-65)-43)+8×1。返回-1816。
【说明】
可以认定给定的字符串一定是正确的公式,不需要对str做公式有效性检查。
如果是负数就需要有括号括起来,比如4*(-3)。但如果负数作为公式的开头或者括号部分的开头,则可以没有括号,比如-3*4和(-3*4)都是合法的。
- 不需要考虑溢出问题
本题考查面试者设计程序和代码的能力。 实现方式有很多种,本书提供一种方法供读者参考,假设value方法是一个递归过程。具体解释如下:
从左到右遍历str , 开始遍历或遇到字符'(' 时, 就进行递归过程。 当发现str遍历完。或者遇到字符 ')' 时 ,就结束递归过程。比如“”3*(4+5)+7“”一开始遍历就进入递归过程value(str, 0 ) , 在递归过程value (str, 0)中继续遍历 str , 当遇到字符 '(' 时 , 递归过程value(str, 0)又重复调用递归过程 value (str , 3 ) ,然后在 value(str, 3 )中继续遍历str,当遇到字符‘)’ 时, 递归过程value (str , 3 ) 结束 , 并向递归过程 value (str, 0 ) 返回两个结果,第一结果是value(str, 3)遍历过的公式字符子串的结果,即“”5+4“” == 9 , 第二个结果是 value (str, 3 ) 遍历到的位置,即字符‘)’的位置 == 6 。递归过程value(str , 0 ) 收到这两个结果后,既可知道交给value(str,3) 过程处理的字符串结果是多少(“”5+4“”的结果为9),又可知道自己下一步该从什么位置继续遍历(从位置6的下一个位置(即位置7)继续遍历)。
-------------------------------------------------------------------------------------------------------------------------
全部解析过程可看 : 程序员代码面试指南:IT名企算法与数据结构题目最优解 p276
C++代码如下 :
#include <iostream>
#include <vector>
#include <deque>
#include <string>
using namespace std;
class Solution
{
public:
int getVaule(string exp){
return Value(exp, 0)[0];
}
vector<int> Value(string chars, int i)
{
deque<string> deq;
int pre = 0;
vector<int> bra(2);
while (i < chars.length() && chars[i] != ')')
{
if (chars[i] >= '0' && chars[i] <= '9')
{
pre = pre * 10 + chars[i++] - '0';
}
else if (chars[i] != '(') //表示为符号 + - * /
{
addNum(deq, pre);
deq.push_back(chars.substr(i, 1)); // 将该符号加入双端队列
i++; //计算下一个位置
pre = 0;
}
else
// 表示为 ( , 进行下一轮递归,返回两个值 :
//一个是递归的结果即(...)内的计算结果 , 另一个是次轮递归 ) 所在的位置
{
bra = Value(chars, i + 1);
pre = bra[0];
i = bra[1] + 1; //计算返回上一层计算下一个位置
}
}
addNum(deq, pre); //遇到 ) 就到这 , 例(3+4 ) ,
//此时 队列deq中为 3 , + , 此时4 为pre ,需要再加一次
return vector<int> {getNum(deq), i };
}
void addNum(deque<string>& deq, int num) //相对于去掉乘法和除法重新放回队列
{
if (!deq.empty())
{
int cur = 0;
string top = deq.back();
deq.pop_back();
if ((top == "+") || top == "-")
{
deq.push_back(top);
}
else
{
cur = atoi(deq.back().c_str());
deq.pop_back();
num = (top == "*" ? (cur*num) : cur / num);
}
}
deq.push_back(to_string(num)); //将num放入队列
}
int getNum(deque<string> & deq) // 此时deq中只有+ , - 顺序计算即可 ;
{
int res = 0;
bool add = true;
string cur = "";
int num = 0;
while (!deq.empty())
{
cur = deq.front();
deq.pop_front();
if (cur == "+") add = true;
else if (cur == "-") add = false;
else
{
num = atoi(cur.c_str());
res += add ? num : (-num);
}
}
return res;
}
};
int main()
{
Solution a;
string s = "48*((70-65)-43)+8*1";
string s1 = "3+1*4";
cout << a.getVaule(s1) << endl;
system("pause");
return 0;
}