224. Basic Calculator + 227. Basic Calculator II
▶ 两个四则表达式运算的题目,第 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的更多相关文章
- leetcode 224. Basic Calculator 、227. Basic Calculator II
这种题都要设置一个符号位的变量 224. Basic Calculator 设置数值和符号两个变量,遇到左括号将数值和符号加进栈中 class Solution { public: int calcu ...
- LeetCode 227. 基本计算器 II(Basic Calculator II)
227. 基本计算器 II 227. Basic Calculator II 题目描述 实现一个基本的计算器来计算一个简单的字符串表达式的值. 字符串表达式仅包含非负整数,+,-,*,/ 四种运算符和 ...
- 【LeetCode】227. Basic Calculator II 解题报告(Python)
[LeetCode]227. Basic Calculator II 解题报告(Python) 标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: h ...
- [LeetCode] 227. Basic Calculator II 基本计算器之二
Implement a basic calculator to evaluate a simple expression string. The expression string contains ...
- [Basic] The most basic things about java
[Basic] The most basic things about java // */ // ]]> [Basic] The most basic things about java ...
- Java实现 LeetCode 227 基本计算器 II(二)
227. 基本计算器 II 实现一个基本的计算器来计算一个简单的字符串表达式的值. 字符串表达式仅包含非负整数,+, - ,*,/ 四种运算符和空格 . 整数除法仅保留整数部分. 示例 1: 输入: ...
- 【LeetCode】227. Basic Calculator II
Basic Calculator II Implement a basic calculator to evaluate a simple expression string. The express ...
- [LeetCode] 227. Basic Calculator II 基本计算器 II
Implement a basic calculator to evaluate a simple expression string. The expression string contains ...
- LeetCode#227.Basic Calculator II
题目 Implement a basic calculator to evaluate a simple expression string. The expression string contai ...
随机推荐
- 雷林鹏分享:Ruby 数据库访问 - DBI 教程
Ruby 数据库访问 - DBI 教程 本章节将向您讲解如何使用 Ruby 访问数据库.Ruby DBI 模块为 Ruby 脚本提供了类似于 Perl DBI 模块的独立于数据库的接口. DBI 即 ...
- JSP 点击量统计
JSP 点击量统计 有时候我们需要知道某个页面被访问的次数,这时我们就需要在页面上添加页面统计器,页面访问的统计一般在用户第一次载入时累加该页面的访问数上. 要实现一个计数器,您可以利用应用程序隐式对 ...
- Java队列的两种实现方式
1. 基于数组 package Algorithm.learn; import java.util.Arrays; /** * Created by liujinhong on 2017/3/7. * ...
- uva-10491-经典问题
https://vjudge.net/problem/UVA-10491 有a个门后是牛,b个门后是车,一开始随机选一个门,然后主持人会打开c(c<a)个为牛的门,之后可以选择换门(这里要求总是 ...
- @Column实体类中的使用(二十三)
- hdu1512
题解: 每一次合并两个对 修改操作就和普通的堆一样 代码: #include<cstring> #include<cmath> #include<cstdio> # ...
- 数据库链接池 durid 的配置参数详解
这里我主要介绍druid 比较重要的参数解释,不做druid的使用介绍,druid虽然功能强大,但是如果对配置参数理解不到位,性能非但不能达到很优,而且会出现很多异常,所以使用druid之前一定要清楚 ...
- Python3 字典Dict(十三)
Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度. 字典是另一种可变容器模型,且可存储任意类 ...
- Centos系统更改yum源为163
Centos安装好之后,按照网上教程对yum源进行修改,但更新之后发现总是提示更新失败,到163网站上查找资源发现目前大部分网上的教程都写错地址了,呵呵 下面是正确的办法,请参考 1.进入存放源配置的 ...
- 转: android之虚拟机访问tomcat服务器资源
最近在研究Android虚拟机访问tomcat服务器资源,所以找了个时间写下这篇博客和大家分享一下心得. 其实Android虚拟机访问tomcat服务器非常的简单,只要不要弄错IP地址就可以访问tom ...