▶ 两个四则表达式运算的题目,第 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. Solaris 11 让 ls 的输出 带上颜色

    Solaris 默认的ls , 是不会显示 文件和文件夹的颜色的. 我们可以利用 gnu 的 ls 命令. 修改:~/.bashrc alias ls='/usr/gnu/bin/ls --color ...

  2. 2016 CCPC Hangzhou Onsite

    A:题意:n个格子排成一排,每个a[i],要求重排成k个,每个人数相同,合并两个和划分成两个(可以不等)都是花费为1,问最小花费 题解:从前往后贪心即可,由于哪个地方忘开ll,wa了,全改成ll就过了 ...

  3. Spring MVC 实现跨域资源 CORS 请求

    说到 AJAX 跨域,很多人最先想到的是 JSONP.的确,JSONP 我们已经十分熟悉,也使用了多年,从本质上讲,JSONP 的原理是给页面注入一个 <script>,把远程 JavaS ...

  4. 启动tornado项目,hello world

    新建一个env虚拟环境 mkvirtualenv toenv 在虚拟环境中安装tornado workon toenv pip install tornado 在D盘中新建tornado项目文件夹,就 ...

  5. lmdb数据格式

    http://deepdish.io/2015/04/28/creating-lmdb-in-python/ https://lmdb.readthedocs.org/en/release/ http ...

  6. 离散数学:用C语言来判断集合存在的二元关系

    用C语言来判断是否满足自反,反自反,非自反,对称,反对称,非对称和传递性 也不知道写的对不对.没有大量验证,但是随便找的一些关系测试的没毛病,如果错了,欢迎各位大佬留言 #include<bit ...

  7. 51Nod 1049:最大子段和(dp)

    1049 最大子段和  基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 N个整数组成的序列a[1],a[2],a[3],-,a[n],求该序列如a[i]+ ...

  8. 6-3 Add Two Polynomials(20 分)

    Write a function to add two polynomials. Do not destroy the input. Use a linked list implementation ...

  9. gqlgen golang graphql server 基本试用

    gqlgen golang 的graphql server 具体代码参考https://github.com/rongfengliang/gqlgen-demo 特点 模型优先 类型安全 代码生成 安 ...

  10. lnmp -- 解决Warning: scandir() has been disabled for security reasons in…的问题

    原因:LNMP 0.9禁用了部分存在危险的PHP函数 LNMP0.9禁用的PHP函数包括:passthru, exec, system, chroot, scandir, chgrp, chown, ...