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 ...
随机推荐
- Python 中的那些坑总结——持续更新
1.三元表达式之坑 很显然,Python把第一行的(10 + 4)看成了三元表达式的前部分,这个坑是看了<Python cookbook>(P5)中学到的,书中的代码: 2.Python生 ...
- c++运算符优先级表
优先级 操作符 描述 例子 结合性 1 () [] -> . :: ++ -- 调节优先级的括号操作符 数组下标访问操作符 通过指向对象的指针访问成员的操作符 通过对象本身访问成员的操作符 作用 ...
- java 获取本机的IP地址
方法一:这种方式有一定的局限性,在Linux下的执行结果是:本机的IP = xxx/127.0.1.1 (其中xxx是你的计算机名) public void getLocalIPAddress() { ...
- lister.ora配置
SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (SID_NAME = PLSExtProc) (ORACLE_HOME = D:\ ...
- 网路防火墙iptables
linux操作系统自身可以充当交换机,还可以当路由器,也就是说linux多网卡之间拥有互相转发数据包的能力,这种能力的实现主要依靠的是防火墙的功能进行数据包的转发和入站. 路由选择点,就是在一个点分辨 ...
- 如何导入数据到Mysql
有两种方法: 1.如果是.sql后缀的数据库文件,使用phpmyadmin中的导入功能导入即可,导入前需要新建数据库名. 2.如果导入的是文件夹(内含.frm,.myd,.myi,.opt类型文件), ...
- 更新.xsd后,rdlc 数据源更新不了
- Python基础学习----名片管理系统学习笔记
主文件: import stu_tools while True: stu_tools.select_list() select = input("请输入您的操作指令") prin ...
- Django 之 富文本编辑器-tinymce
这里的富文本编辑器以 tinymce 为例. 环境:ubuntu 16.04 + django 1.10 + python 2.7 ubuntu安装tinymce: python 2.7 $ sudo ...
- 【java多线程】java的内存模型
Java内存模型 下面是我从百度上引入的一张具有代表性的图 ①解释:我根据这张图来解释java内存模型,从图中可以看出每个线程都需要从主内存中读取操作,这个就是java内存模型的规定之一,所有的变量存 ...