基本计算器 IV
给定一个表达式如 expression = "e + 8 - a + 5"
和一个求值映射,如 {"e": 1}
(给定的形式为 evalvars = ["e"]
和 evalints = [1]
),返回表示简化表达式的标记列表,例如 ["-1*a","14"]
- 表达式交替使用块和符号,每个块和符号之间有一个空格。
- 块要么是括号中的表达式,要么是变量,要么是非负整数。
- 变量是一个由小写字母组成的字符串(不包括数字)。请注意,变量可以是多个字母,并注意变量从不具有像
"2x"
或"-x"
这样的前导系数或一元运算符 。
表达式按通常顺序进行求值:先是括号,然后求乘法,再计算加法和减法。
- 例如,
expression = "1 + 2 * 3"
的答案是["7"]
。
输出格式如下:
-
对于系数非零的每个自变量项,我们按字典排序的顺序将自变量写在一个项中。
- 例如,我们永远不会写像
“b*a*c”
这样的项,只写“a*b*c”
。
- 例如,我们永远不会写像
-
项的次数等于被乘的自变量的数目,并计算重复项。我们先写出答案的最大次数项,用字典顺序打破关系,此时忽略词的前导系数。
- 例如,
"a*a*b*c"
的次数为 4。
- 例如,
-
项的前导系数直接放在左边,用星号将它与变量分隔开(如果存在的话)。前导系数 1 仍然要打印出来。
-
格式良好的一个示例答案是
["-2*a*a*a", "3*a*a*b", "3*b*b", "4*a", "5*c", "-6"]
。 -
系数为
0
的项(包括常数项)不包括在内。
- 例如,
“0”
的表达式输出为[]
。
- 例如,
**注意:**你可以假设给定的表达式均有效。所有中间结果都在区间 [-231, 231 - 1]
内。
示例 1:
输入:expression = "e + 8 - a + 5", evalvars = ["e"], evalints = [1]
输出:["-1*a","14"]
示例 2:
输入:expression = "e - 8 + temperature - pressure",
evalvars = ["e", "temperature"], evalints = [1, 12]
输出:["-1*pressure","5"]
示例 3:
输入:expression = "(e + 8) * (e - 8)", evalvars = [], evalints = []
输出:["1*e*e","-64"]
提示:
1 <= expression.length <= 250
expression
由小写英文字母,数字'+'
,'-'
,'*'
,'('
,')'
,' '
组成expression
不包含任何前空格或后空格expression
中的所有符号都用一个空格隔开0 <= evalvars.length <= 100
1 <= evalvars[i].length <= 20
evalvars[i]
由小写英文字母组成evalints.length == evalvars.length
-100 <= evalints[i] <= 100
代码:
//模拟 多项式
class Solution {
public:
class PloyCal{
private:
vector<int> coefs;
vector<vector<string>> alphas;
public:
PloyCal(){ }
PloyCal(int coef, string alpha){
coefs.push_back(coef);
alphas.emplace_back(vector<string>{alpha});
}
~PloyCal(){ }
PloyCal& operator+=(PloyCal& other){
int n = other.coefs.size();
for(int i = 0; i < n; i ++){
this->add(other.coefs[i], other.alphas[i]);
}
return *this;
}
PloyCal& operator-=(PloyCal& other){
int n = other.coefs.size();
for(int i = 0; i < n; i ++){
this->add(-other.coefs[i], other.alphas[i]);
}
return *this;
}
PloyCal& operator*=(PloyCal& other){
PloyCal memo = *this;
*this = PloyCal{};
int n = other.coefs.size();
for(int i = 0; i < n; i ++){
PloyCal temp = memo;
temp.mul(other.coefs[i], other.alphas[i]);
(*this) += temp;
}
return *this;
}
// 减就是加-c
void add(int c, vector<string>& a){
if(c == 0) return;
sort(a.begin(), a.end());
for(int i = 0; i < alphas.size(); i ++){
if(alphas[i] == a){
coefs[i] += c;
if(coefs[i] == 0){
coefs.erase(coefs.begin() + i);
alphas.erase(alphas.begin() + i);
}
return;
}
}
coefs.push_back(c);
alphas.push_back(a);
}
// 乘法
void mul(int c, vector<string>& a){
if(c == 0){
coefs.clear();
alphas.clear();
return;
}
for(int i = 0; i < coefs.size(); i ++) coefs[i] *= c;
if(a.size() && a[0].size()){
for(auto& alpha: alphas){
if(alpha.size() && alpha.back().size() == 0) alpha.pop_back();
copy(a.begin(), a.end(), back_inserter(alpha));
sort(alpha.begin(), alpha.end());
}
}
}
vector<string> get_poly(){
sort_poly();
int n = coefs.size();
vector<string> res;
for(int i = 0; i < n; ++i){
if(coefs[i] == 0) continue;
string coef = to_string(coefs[i]);
string alpha;
for(string& s: alphas[i]){
if(alpha.size()) alpha += "*";
alpha += s;
}
if(alpha.size()) res.push_back(coef + "*" + alpha);
else res.push_back(coef);
}
return res;
}
void sort_poly(){
int n = coefs.size();
vector<int> t(n);
for(int i = 0; i < n; i ++) t[i] = i;
for(int i = 0; i < n; i ++){
while(alphas[i].size() && alphas[i].back().size() == 0) alphas[i].pop_back();
}
sort(t.begin(), t.end(), [this](int lhs, int rhs){
int len1 = alphas[lhs].size(), len2 = alphas[rhs].size();
if(len1 != len2) {
return len1 > len2;
}
return alphas[lhs] < alphas[rhs];
});
vector<int> sort_coefs(n);
vector<vector<string>> sort_alphas(n);
for(int i = 0; i < n; i ++){
sort_coefs[i] = coefs[t[i]];
sort_alphas[i] = alphas[t[i]];
}
coefs = sort_coefs;
alphas = sort_alphas;
}
void show(){
puts("current poly is:");
for(int i = 0; i < coefs.size(); i ++){
cout << coefs[i] << ":";
for(string&s : alphas[i]) cout << s << "*";
cout << endl;
}
}
};
vector<PloyCal> num; // 操作数
vector<char> op; // 操作符
// poly1 op poly2
void cal(){
int n = num.size();
char cur_op = op.back();
op.pop_back();
if(cur_op == '+'){
num[n-2] += num[n-1];
}else if(cur_op == '-'){
num[n-2] -= num[n-1];
}else{
num[n-2] *= num[n-1];
}
num.pop_back();
}
vector<string> basicCalculatorIV(string expr, vector<string>& var, vector<int>& var_num) {
unordered_map<string, int> alpha2coef;
for(int i = 0; i < var.size(); i ++) alpha2coef[var[i]] = var_num[i];
int n = expr.size();
int i = 0;
while(i < n){
if(expr[i] == ' ') {
i ++;
continue;
}
if(expr[i] == '(') {
op.push_back('(');
i ++;
continue;
}
if(expr[i] == ')'){
while(op.back() != '(') cal();
op.pop_back();
i ++;
continue;
}
if(expr[i] == '+' || expr[i] == '-'){
while(op.size() && op.back() != '(') cal();
op.push_back(expr[i]);
i ++;
continue;
}
if(expr[i] == '*'){
while(op.size() && op.back() == '*') cal();
op.push_back(expr[i]);
i ++;
continue;
}
int space = i+1;
while(space < n && expr[space] != ' ' && expr[space] != '(' && expr[space] != ')') space ++;
// 生成新Poly
int coef = 1;
string alpha;
// 操作数系数
if(expr[i] < 'a') {
coef = stoi(expr.substr(i, space-i));
}
// 操作数变量
else {
if(alpha2coef.count(expr.substr(i, space-i))){
coef = alpha2coef[expr.substr(i, space-i)];
}else{
alpha = expr.substr(i, space-i);
}
}
num.push_back(PloyCal{coef, alpha});
i = space;
}
while(op.size()) cal();
return num[0].get_poly();
}
};