▶ 两个四则表达式运算的题目,第 770 题 Basic Calculator IV 带符号计算不会做 Orz,第 772 题 Basic Calculator III 要收费 Orz。

▶ 自己的全能版代码,28 ms,采用表达式中缀转后缀,然后利用栈来计算。支持加减乘除幂模,一模一样的代码刷掉了这两题,就是效率比较低,28 ms

 class Solution
{
public:
int calculate(string s)//计算器,输入表达式,输出计算结果
{
string out;
mid_to_last(s, out);
return calculate_last(out);
}
private:
int power(int a, int b)// 整数幂运算,a^b
{
int output;
for (output = ; b > ; a *= a, b >>= )
{
if (b & )
output *= a;
}
return output;
}
int numread(const string & in, int start, string & output)//读取字符串数字,返回包括前导空白的数字长度
{
int i, blankLen;
for (i = start, blankLen = , output = ""; in[i] == ' '; i++, blankLen++);// 跳过前导空白
if (in[i] == '-') // -3
i++;
else if (in[i] == '+') // +3
i++, blankLen++;
if (in[i]<'' || in[i]>'') // 不是数字
return ;
for (; in[i] >= '' && in[i] <= ''; i++); // 寻找有效字符末尾
output = in.substr(start + blankLen, i - start - blankLen);
return blankLen + output.size();
}
int rankSign(char c)//规定运算等级
{
switch (c)
{
case '\0':
return -;
case '':case '':case '':case '':case '':case '':case '':case '':case '':case '':
return ;
case '(':case ')':
return ;
case '+':case '-':
return ;
case '*':case '/':case '%':
return ;
case '^':
return ;
default:
return -;
}
}
bool mid_to_last(const string & in, string & out)//表达式中缀转后缀
{
int pin, len;
string tempStr;
stack<char> sym;
for (out = "", pin = ; pin < in.size() && in[pin] != '\0'; pin++)
{
for (; in[pin] == ' '; pin++); // 处理间隔空格
for (; in[pin] == '('; sym.push(in[pin++]));// 连续的 '(' 压栈 assert(len = numread(in, pin, tempStr)); // 读数字到 tmp 中
pin += len; //向后跳位
out += tempStr + ' '; // 读取的字符串输出到 out 中 for (; in[pin] == ' '; pin++); // 处理间隔空格
for (; in[pin] == ')'; pin++, sym.pop()) // 遇到 ')',把栈中最近一个 '(' 之后的部分吐空,最后把 '(' 也吐掉
for (; sym.top() != '('; out += sym.top(), out += ' ', sym.pop()); for (; in[pin] == ' '; pin++); // 处理间隔空格
if (in[pin] == '\0') //表达式已空,正常结束,把栈吐空,结束
{
for (; !sym.empty(); out += sym.top(), out += ' ', sym.pop());
return true;
} if (sym.empty() || rankSign(in[pin]) > rankSign(sym.top())) //空栈或表达式中算符等级高,压栈
sym.push(in[pin]);
else
{
for (; !sym.empty() && rankSign(in[pin]) <= rankSign(sym.top());) //吐到栈中算符等级小于表达式中字符为止
out += sym.top(), out += ' ', sym.pop();
sym.push(in[pin]);
}
}
return false; // 表达式在错误的地方结束,报错
}
int calculate_last(const string & in)//输入后缀表达式计算
{
int pin, len, tempNum;
string tempStr;
stack<int> number;
for (pin = ; pin<in.size() && in[pin] != '\0';)// 连着字符和空白一起跳过去
{
// 取数字
if(len = numread(in, pin, tempStr))
{
number.push(atoi(tempStr.c_str()));
pin += len + ;
continue;
}
// 处理算符
tempNum = number.top(), number.pop();
assert(!number.empty()); // 缺少第二个参与运算的数字
switch (in[pin])
{
case '+': tempNum = number.top() + tempNum; break;
case '-': tempNum = number.top() - tempNum; break;
case '*': tempNum = number.top() * tempNum; break;
case '/': assert(tempNum), tempNum = number.top() / tempNum; break; // 检查分母非零
case '%': assert(tempNum), tempNum = number.top() % tempNum; break; // 检查模数非零
case '^': assert(tempNum >= ), tempNum = power(number.top(), tempNum); break; // 检查指数非负
default:
assert(false); // 混入了其他符号
}
number.pop(), number.push(tempNum);
pin += ;
}
assert(!(number.empty() || number.size() > ));// 栈空或者栈中有不止一个元素
return number.top();
}
};

▶ 第 224 题,表达式仅含加减法,支持小括号

● 大佬的代码,13 ms,注意到只含 '+ - ( )' 的表达式可以完全去括号,然后从左向右依次计算,用一个变量 sign 记录当前数字在去括号过程中引入的附加符号

 class Solution
{
public:
int calculate(string s)
{
stack<int> st;
int i, res, sign, num;
for (i = res = , sign = ; i < s.size();)
{
switch (s[i])
{
case '':case '':case '':case '':case '':case '':case '':case '':case '':case '':
{
for (num = ; i < s.size() && s[i] >= '' && s[i] <= ''; num = ( * num) + s[i] - '', i++);
res += (sign * num);
break;
}
case ' ':
for (; i < s.size() && s[i] == ' '; i++); break;
case '(':
st.push(res), st.push(sign), res = , sign = , i++; break;
case ')':
res = res * st.top(), st.pop(), res += st.top(), st.pop(), i++; break;
default:
sign = - s[i], i++; break; // 44 - s[i] 等价于 (s[i] == '+') ? 1 : -1,因为 '+' == 43,'-' == 45
}
}
return res;
}
};

▶ 第227 题,表达式含加减乘除,没有小括号

● 大佬的代码,13 ms,使用栈

 class Solution
{
public:
int calculate(string s)
{
const int len = s.size();
stack<int> st;
int i, num, temp;
char sign;
for (i = num = , sign = '+'; i < len; i++)
{
if (s[i] >= '' && s[i] <= '')
num = num * + s[i] - '';
if ((s[i] < '' || s[i] > '') && s[i] != ' ' || i == len - )
{
if (sign == '-')
st.push(-num);
else if (sign == '+')
st.push(num);
else if (sign == '*')
temp = st.top(), st.pop(), st.push(temp * num);
else if (sign == '/')
temp = st.top(), st.pop(), st.push(temp / num);
sign = s[i];
num = ;
}
}
for (temp = ; !st.empty(); temp += st.top(), st.pop());
return temp;
}
};

● 大佬的代码,12 ms,与上一个方法算法相同,不使用栈

 class Solution
{
public:
void trim(string & s)
{
int index = ;
if (!s.empty())
for (; (index = s.find(' ', index)) != string::npos; s.erase(index, ));
}
int calculate(string s)
{
trim(s); // 去掉所有空格,原 Java 代码:s = s.trim().replaceAll(" +", "");
int length = s.size();
int i, res;
long preVal, curVal;
char sign;
for (i = res = preVal = , sign = '+'; i < length;)
{
for (curVal = ; i < length && s[i] >= '' && s[i] <= ''; i++)
curVal = curVal * + (s[i] - '');
if (sign == '+')
res += preVal, preVal = curVal;
else if (sign == '-')
res += preVal, preVal = -curVal
else if (sign == '*')
preVal = preVal * curVal;
else if (sign == '/')
preVal = preVal / curVal;
if (i < length)
sign = s[i], i++;
}
res += preVal;
return res;
}
};

● 大佬的方法,18 ms,三步走战略,先提取 token 替换符号,再计算乘除法,最后计算加减法

 class Solution
{
public:
int calculate(string s)
{
if (s.size() == )
return ;
vector<int> exp, exp1; bool isLastDig = false;
int i, curIdx, val, last, res;
for (i = curIdx = val = ; i < s.length(); i++)// 第一轮 string 转为 vector<int> 类型的 token,包括计算符
{
if (s[i] == ' ')
continue;
val = s[i];
if (val >= '' && val <= '')
{
if (isLastDig)
exp[curIdx] = exp[curIdx] * + (int)(val - '');
else
{
isLastDig = true;
exp.push_back(val - '');
}
}
else
{
isLastDig = false;
if (s[i] == '-') // +-*/ 分别用 -2,-1,-3,-4表示
exp.push_back(-);
else if (s[i] == '+')
exp.push_back(-);
else if (s[i] == '*')
exp.push_back(-);
else if (s[i] == '/')
exp.push_back(-);
curIdx += ;
}
}
for (i = ; i < exp.size(); i++)// 第二轮,进行乘除运算
{
if (exp[i] == -)
{
last = exp1.back();
exp1.pop_back();
exp1.push_back(last * exp[i + ]);
i++;
}
else if (exp[i] == -)
{
last = exp1.back();
exp1.pop_back();
exp1.push_back(last / exp[i + ]);
i++;
}
else
exp1.push_back(exp[i]);
}
if (exp1.size() == )// 只有乘除法的表达式,已经算完了
return exp1[];
for (i = , res = exp1[]; i < exp1.size(); i++)// 第三轮,进行加减运算
{
if (exp1[i] == -)
res -= exp1[i + ];
else if (exp1[i] == -)
res += exp1[i + ];
}
return res;
}
};

● 大佬的神奇方法,19 ms,可能是 VS2015 支持的 C++ 版本低,暂不支持编译

 class Solution
{
public:
int calculate(string s)
{
istringstream in('+' + s + '+');
long long total = , term = , n;
char op;
while (in >> op)
{
if (op == '+' || op == '-')
{
total += term;
in >> term;
term *= - op;
}
else
{
in >> n;
if (op == '*')
term *= n;
else
term /= n;
}
}
return total;
}
};

224. Basic Calculator + 227. Basic Calculator II的更多相关文章

  1. leetcode 224. Basic Calculator 、227. Basic Calculator II

    这种题都要设置一个符号位的变量 224. Basic Calculator 设置数值和符号两个变量,遇到左括号将数值和符号加进栈中 class Solution { public: int calcu ...

  2. LeetCode 227. 基本计算器 II(Basic Calculator II)

    227. 基本计算器 II 227. Basic Calculator II 题目描述 实现一个基本的计算器来计算一个简单的字符串表达式的值. 字符串表达式仅包含非负整数,+,-,*,/ 四种运算符和 ...

  3. 【LeetCode】227. Basic Calculator II 解题报告(Python)

    [LeetCode]227. Basic Calculator II 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: h ...

  4. [LeetCode] 227. Basic Calculator II 基本计算器之二

    Implement a basic calculator to evaluate a simple expression string. The expression string contains ...

  5. [Basic] The most basic things about java

    [Basic] The most basic things about java // */ // ]]>   [Basic] The most basic things about java ...

  6. Java实现 LeetCode 227 基本计算器 II(二)

    227. 基本计算器 II 实现一个基本的计算器来计算一个简单的字符串表达式的值. 字符串表达式仅包含非负整数,+, - ,*,/ 四种运算符和空格 . 整数除法仅保留整数部分. 示例 1: 输入: ...

  7. 【LeetCode】227. Basic Calculator II

    Basic Calculator II Implement a basic calculator to evaluate a simple expression string. The express ...

  8. [LeetCode] 227. Basic Calculator II 基本计算器 II

    Implement a basic calculator to evaluate a simple expression string. The expression string contains ...

  9. LeetCode#227.Basic Calculator II

    题目 Implement a basic calculator to evaluate a simple expression string. The expression string contai ...

随机推荐

  1. 在EORow或者VORow中对数据进行重复性校验

    需求:在设置付款条件时不允许账期+付款方式重复. 由于本次需求仅需要对VO缓存中的数据进行重复性校验,所以仅需进行缓存遍历即可,不需要校验数据库. 方式1,在EORow的进行数据校验. public ...

  2. POJ 3126 Prime Path 广度优先搜索 难度:0

    http://poj.org/problem?id=3126 搜索的时候注意 1:首位不能有0 2:可以暂时有没有出现在目标数中的数字 #include <cstdio> #include ...

  3. 利用Sonar定制自定义JS扫描规则(三)——SSLR JavaScript Toolkit 使用说明

    在上一篇blog中讲了在sonar中如何新增自定义的JS规则,这里面比较难的地方是XPath语句的编写,而要编写正确的XPath语句,首先要拿到语法的AST,下面我们就来介绍如何使用SSLR Java ...

  4. 安装xadmin后台管理插件

    django自带的admin后台管理功能太少.使用国人开发的xadmin后台,使用pip install xadmin安装在线包时,会出错,其中的README.rst是utf8格式,我们win7系统默 ...

  5. WebGL编程指南案例解析之绘制三角形

    //案例3.绘制三角形,将顶点数据存到缓冲区对象(gl.ARRAY_BUFFER)中,然后顶点着色器从里面读数据(3个顶点) //顶点着色器中去掉gl_PointSize = 10.0,绘制三角不能设 ...

  6. 《DSP using MATLAB》示例Example 10.4

    代码: %% ------------------------------------------------------------------------ %% Output Info about ...

  7. Linux内核配置---menuconfig

    1. 示例 config SGI_NEWPORT_CONSOLE tristate "SGI Newport Console support" depends on SGI_IP2 ...

  8. 结构化日志类库 ---- Serilog库

    在过去的几年中,结构化日志已经大受欢迎.而Serilog是 .NET 中最著名的结构化日志类库 ,我们提供了这份的精简指南来帮助你快速了解并运用它. 0. 内容 设定目标 认识Serilog 事件和级 ...

  9. stacks and queues--codility

    lesson 7: stacks and queues 1. Nesting 2. StoneWall 3. Brackets 4. Finsh lesson 7: stacks and queues ...

  10. Asp.net MVC Comet 推送

    一.简介 在Asp.net MVC实现的Comet推送的原理很简单. 服务器端:接收到服务器发送的AJAX请求,服务器端并不返回,而是将其Hold住,待到有东西要通知客户端时,才将这个请求返回. 客户 ...