您的位置:首页 > 其它

LeetCode OJ——Basic Calculator

2015-12-01 10:47 309 查看
题目:

Implement a basic calculator to evaluate a simple expression string.

The expression string may contain open ( and closing parentheses ), the plus + or minus sign -, non-negative integers and empty spaces .

You may assume that the given expression is always valid.

Some examples:

“1 + 1” = 2

” 2-1 + 2 ” = 3

“(1+(4+5+2)-3)+(6+8)” = 23

Note: Do not use the eval built-in library function.

代码:

class Solution {
public:
int calculate(string s) {
stack<string> stk;
string tmp, ss;
ostringstream oss;

//s.erase(0, s.find_first_not_of(" ")); // 去掉头部空格
//s.erase(s.find_last_not_of(" ") + 1); // 去掉尾部空格
vector<string> vec_s;

for (unsigned i = 0; i < s.length(); i++)   //去掉空格
{
if (s[i] != ' ')
{
ss.push_back(s[i]);
}
}
s = ss;
unsigned i = 0;
ss.clear();
while (i < s.length())      //将s分裂成新的字符串,例 "1 - 1 2 + ( 3 - 34)"
{                           //转换成"1", "-", "12", "+", "(", "3", "-", "34", ")"
//ss.clear();
if (isdigit(s[i]))
{
ss.push_back(s[i]);
i++;
}
else{
if (!ss.empty())
{
vec_s.push_back(ss);
ss.clear();
}
ss.push_back(s[i]);
vec_s.push_back(ss);
ss.clear();
i++;
}
}
if (!ss.empty())
{
vec_s.push_back(ss);
ss.clear();
}
ss.clear();

if (vec_s.size() == 0)     //容器为空,表明s不存在非空格字符
{
return 0;
}
else if (vec_s.size() == 1)    //容器长度为1,表明s只含有数字字符
{

return atoi(vec_s[0].c_str());
}
else{
tmp.push_back(s[0]);
stk.push(vec_s[0]);

for (unsigned i = 1; i < vec_s.size(); i++)
{
if (vec_s[i] == "(")     //当前字符为'('
{
tmp.clear();
tmp.push_back('(');
stk.push(tmp);
//stk.push(vec_s[i]);

}
else if (vec_s[i] == "+")     //当前字符为+
{
//栈顶元素为数字,+号后面的字符s[i+1](+号后面一定存在字符,否则字符串不合法)也为数字,即+号前后都为数字可运算
if (isdigit(tmp[tmp.size()-1]) && isdigit(vec_s[i+1][vec_s[i+1].size()-1]))
{
//tmp.pop_back();       //此时tmp中原先存储的数字并没有消去
oss.str("");
oss << atoi(tmp.c_str()) + atoi(vec_s[i+1].c_str());
tmp = oss.str();
stk.pop();
stk.push(tmp);  //将运算后的数字入栈
i++;
}
else{
tmp.clear();    //每次入栈前都将tmp清空
tmp = vec_s[i];
stk.push(tmp);
}
}
else if (vec_s[i] == "-")     //当前字符为-
{
//栈顶元素为数字,-号后面的字符s[i+1](-号后面一定存在字符,否则字符串不合法)也为数字,即-号前后都为数字可运算
if (isdigit(tmp[tmp.size()-1]) && isdigit(vec_s[i + 1][vec_s[i + 1].size() - 1]))
{
oss.str("");
oss << (atoi(tmp.c_str()) - atoi(vec_s[i + 1].c_str()));     //-号前后元素都为数字,故可进行运算
tmp = oss.str();
stk.pop();
stk.push(tmp);  //将运算后的数字入栈
i++;
}
else{
tmp.clear();
tmp = vec_s[i];
stk.push(tmp);
}
}
else if (isdigit(vec_s[i][vec_s[i].size() - 1]))   //当前字符为数字
{
tmp.clear();
tmp = vec_s[i];
stk.push(tmp);

}
else if(vec_s[i] == ")")     //当前字符为')',表示栈中一定存在'('
{
tmp = stk.top();  //栈顶元素为当前()中运算的值
stk.pop();      //删除运算值
stk.pop();      //此时,删除的是'('
if (!stk.empty())//若此时的栈不为空
{
if (stk.top() == "+") //删除的(号前是+号
{
stk.pop();  //先把加号出栈
oss.str("");
oss << (atoi(stk.top().c_str()) + atoi(tmp.c_str()));  //加号前面的数字加上旧的tmp值
}
if (stk.top() == "-")  //删除的(好前面是-号
{
stk.pop();  //先把减号出栈
oss.str("");
oss << (atoi(stk.top().c_str()) - atoi(tmp.c_str()));  //减号前面的数字减上旧的tmp值
}
tmp.clear();
tmp = oss.str();
stk.pop();  //把+或-号前参与运算的数也去掉
}
stk.push(tmp);  //将运算后的值入栈
}
else      //当前字符为空格
{
;
}
}
return atoi(stk.top().c_str());
}

}
};


结果:



思路:

第一步是将字符串中的空格字符去掉

第二步则是将字符串分裂,例s=”1 - 1 2 + ( 3 - 34)”,则分裂后的子串放置在容器中vec_s : “1”, “-“, “12”, “+”, “(“, “3”, “-“, “34”, “)”

第三部是对入栈出栈操作进行运算:

(a) 当遍历的容器中的字符串为“(”号时,入栈

(b) 当该字符串为数字时,入栈

(c) 当该字符串为”+”时,则考虑是否可以进行运 算。因为字符串中只存在+或 -, 因此运算符优先级 相同,只要碰到可以运算的字符串,则可先进行计 算。tmp中存储的是stk.top()的值,即当前字符串 的前一字符串。当”+”号前后均是数字时则可进行 运算。所以要考虑后一字符串是否也为数字, isdigit(vec_s[i + 1][vec_s[i + 1].size() - 1])只对后 一字符串的最后一位字符是否为数字进行判别,其 理由是vec_s[i+1]只有可能是 “(” 或 “)”或“[- ]1XXX”,若最后一位为数字其结果必然也是数 字。同理,isdigit(tmp[tmp.size()-1])。

(d)当为”-“时,同”+”原理。

(e)当为”)”时,则栈中一定存在”(“,切”( )”构成一&个封闭的运算,则该()种的式子一定已经运算过,即栈中存储结构为 ….,(, 数字 。则此时应该出栈2次,将(和数字均出栈。由于合法的字符 中“(”的前面要么是+/-;要么前面没有任何有效字符符,即(已经在最前面。若前面是+/-,则可以更进一步,按照(c)或(d)计算。

(f)将容器遍历完,栈中也只剩最后运算后的结果,返回结果即可

总结:

算法时间复杂度还比较大,算法还需改进。小菜鸟,加油!!!↖(^ω^)↗
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: