高级农民
- 积分
- 1097
- 大米
- 颗
- 鳄梨
- 个
- 水井
- 尺
- 蓝莓
- 颗
- 萝卜
- 根
- 小米
- 粒
- 学分
- 个
- 注册时间
- 2019-1-31
- 最后登录
- 1970-1-1
|
注册一亩三分地论坛,查看更多干货!
您需要 登录 才可以下载或查看附件。没有帐号?注册账号 
x
本帖最后由 玛玛哈哈 于 2021-1-29 05:29 编辑
想问一下大家这道题的思路或对我的代码指出哪里可以优化就更感激不尽了。回答的都加米。
给定一个只包含数字、加减乘除的算术表达式,要求按照运算顺序添加括号。所有数字大小都是 0~9,也就是只有个位。
例子:
输入: 1+4*3-2/1
输出: ((1+(4*3))-(2/1))
我尝试了两种解法, 都是有一部分数据超时了。 一种是用双栈直接对中缀表达式操作, 另外一种是先转成后缀表达式再在后缀表达式上操作。
以下是我的代码: 这道题应该是线性复杂度才能全部过, 我觉得我的代码瓶颈应该是在每次string都需要拼接, 这个要是string很长的情况下开销很大(比如第一种解法中的第30行和第40行)。 想问一下大家有没有办法解决这个问题或者说是有更好的解法。谢谢
这个是用双栈直接对中缀表达式操作
- # include <iostream>
- # include <stack>
- # include <string>
- using namespace std;
- // 不转后缀表达式, 直接对中缀表达式求解
- int getPrecedence(string &oprator) {
- if (oprator == "+" || oprator == "-") return 1;
- return 2;
- }
- bool priorityCompare(string &oprator1, string &oprator2) {
- return getPrecedence(oprator1) >= getPrecedence(oprator2);
- }
- // expr:算术表达式
- // 返回值:加上括号后的表达式
- string solve(string &expr) {
- stack<string> expStack;
- stack<string> opStack;
- for (char c: expr) {
- string s = string(1, c);
- if (isdigit(c)) {
- expStack.push(s);
- } else {
- while (!opStack.empty() && priorityCompare(opStack.top(), s)) {
- string op = opStack.top(); opStack.pop();
- string right = expStack.top(); expStack.pop();
- string left = expStack.top(); expStack.pop();
- string newExp = "(" + left + op + right + string(")");
- expStack.push(newExp);
- }
- opStack.push(s);
- }
- }
- while (expStack.size() > 1) {
- string op = opStack.top(); opStack.pop();
- string right = expStack.top(); expStack.pop();
- string left = expStack.top(); expStack.pop();
- string newExp = "(" + left + op + right + string(")");
- expStack.push(newExp);
- }
- return expStack.top();
- }
- int main() {
- ios::sync_with_stdio(false);
- string s;
- cin >> s;
- cout << solve(s) << '\n';
- return 0;
- }
复制代码
这个是先转成后缀再操作的代码:
- # include <iostream>
- # include <stack>
- # include <vector>
- # include <string>
- using namespace std;
- // 1. use shunting-yard algorithm to convert to RPN
- // 2. use RPN evaluation algorithm to add brackets
- class Op {
- public:
- char oprator;
- int oprand;
- bool isOprand;
- Op() {}
- Op(int oprand) {
- this->isOprand = true;
- this->oprand = oprand;
- }
- Op(char oprator) { // 运算符
- this->isOprand = false;
- this->oprator = oprator;
- }
- };
- int getPrecedence(char &oprator) {
- if (oprator == '+' || oprator == '-') return 1;
- return 2;
- }
- bool priorityCompare(char &oprator1, char &oprator2) {
- return getPrecedence(oprator1) >= getPrecedence(oprator2);
- }
- vector<Op> convertToRPN(string &expr) { // use shunting-yard algorithm
- vector<Op> res;
- stack<Op> opStack;
- for (char c: expr) {
- // check if is digit or not
- Op curOp;
- if (isdigit(c)) { // yes: push to back of res
- curOp = Op(c - '0');
- res.push_back(curOp);
- } else { // no: while top of stack's precedence is no smaller than current operator => push to back of res
- curOp = Op(c);
- while (!opStack.empty() && priorityCompare(opStack.top().oprator, curOp.oprator)) {
- res.push_back(opStack.top());
- opStack.pop();
- }
- opStack.push(curOp);
- }
- }
- while (!opStack.empty()) {
- res.push_back(opStack.top());
- opStack.pop();
- }
- return res;
- }
- // expr:算术表达式
- // 返回值:加上括号后的表达式
- string solve(string expr) {
- stack<string> expStack;
- vector<Op> rpn = convertToRPN(expr);
- for (Op op: rpn) {
- if (op.isOprand) {
- expStack.push(to_string(op.oprand));
- } else {
- string right = expStack.top(); expStack.pop();
- string left = expStack.top(); expStack.pop();
- string newExp = "(" + left + string(1, op.oprator) + right + string(")");
- expStack.push(newExp);
- }
- }
- return expStack.top();
- }
- int main() {
- ios::sync_with_stdio(false);
- string s;
- cin >> s;
- cout << solve(s) << '\n';
- return 0;
- }
复制代码
|
上一篇: 讨论一道最短路径问题下一篇: 推荐刷题做笔记的方法
|