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 ...
随机推荐
- 智课雅思词汇---二十七、形容词后缀-ant/-ent
智课雅思词汇---二十七.形容词后缀-ant/-ent 一.总结 一句话总结: ...的 后缀:-ant ①[形容词后缀] 大部分与-ance或-ancy,相对应,表示属于...的.具有...性质的 ...
- 2018-2019-2 网络对抗技术 20165332 Exp2 后门原理与实践
2018-2019-2 网络对抗技术 20165332 Exp2 后门原理与实践 - 实验内容 任务一:使用netcat获取主机操作Shell,cron启动 任务二:使用socat获取主机操作Shel ...
- 转:Tomcat 7.0配置SSL的问题及解决办法
原文:https://dong-shuai22-126-com.iteye.com/blog/1830209
- maven 工程mybatis自动生成实体类
generatorConfig.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ge ...
- VS2017打包安装程序
VS2017 并不自带安装部署项目,需要在[扩展和更新]中安装插件:Microsoft Visual Studio 2017 Installer Projects(现更名为Microsoft Visu ...
- Beta阶段第1周/共2周 Scrum立会报告+燃尽图 01
作业要求[https://edu.cnblogs.com/campus/nenu/2018fall/homework/2383] 版本控制:https://git.coding.net/liuyy08 ...
- js 的各种排序算法 -- 待续
链接 function quickSort(arr,l,r){ if(l < r){ var i = l, j = r, x = arr[i]; while(i<j){ while(i&l ...
- django-redis 中文文档
Andrey Antukh, niwi@niwi.be 4.7.0 翻译: RaPoSpectre 1. 介绍 django-redis 基于 BSD 许可, 是一个使 Django 支持 Redis ...
- 打造html右键菜单
今天是给大家介绍一款在网页上使用的右键菜单,原作者的网址是:http://51jsr.javaeye.com/blog/305517 这个右键菜单已经非常优秀,不过呢.却是IE Only,而且在DTD ...
- 解决Mybatis没有代码提示
MyBatis xml文件中代码自动提示 工具/原料 eclipse,maven 方法/步骤 1 一.获得mybatis-3-config.dtd.mybatis-3-mapper.dtd 这 ...