Given an expression
such as expression = "e + 8 - a + 5"
and an evaluation map such as {"e": 1}
(given in terms of evalvars = ["e"]
and evalints = [1]
), return a list of tokens representing the simplified expression, such as ["-1*a","14"]
- An expression alternates chunks and symbols, with a space separating each chunk and symbol.
- A chunk is either an expression in parentheses, a variable, or a non-negative integer.
- A variable is a string of lowercase letters (not including digits.) Note that variables can be multiple letters, and note that variables never have a leading coefficient or unary operator like
"2x"
or"-x"
.
Expressions are evaluated in the usual order: brackets first, then multiplication, then addition and subtraction. For example, expression = "1 + 2 * 3"
has an answer of ["7"]
.
The format of the output is as follows:
- For each term of free variables with non-zero coefficient, we write the free variables within a term in sorted order lexicographically. For example, we would never write a term like
"b*a*c"
, only"a*b*c"
. - Terms have degree equal to the number of free variables being multiplied, counting multiplicity. (For example,
"a*a*b*c"
has degree 4.) We write the largest degree terms of our answer first, breaking ties by lexicographic order ignoring the leading coefficient of the term. - The leading coefficient of the term is placed directly to the left with an asterisk separating it from the variables (if they exist.) A leading coefficient of 1 is still printed.
- An example of a well formatted answer is
["-2*a*a*a", "3*a*a*b", "3*b*b", "4*a", "5*c", "-6"]
- Terms (including constant terms) with coefficient 0 are not included. For example, an expression of "0" has an output of [].
Examples:
Input: expression = "e + 8 - a + 5", evalvars = ["e"], evalints = [1] Output: ["-1*a","14"] Input: expression = "e - 8 + temperature - pressure", evalvars = ["e", "temperature"], evalints = [1, 12] Output: ["-1*pressure","5"] Input: expression = "(e + 8) * (e - 8)", evalvars = [], evalints = [] Output: ["1*e*e","-64"] Input: expression = "7 - 7", evalvars = [], evalints = [] Output: [] Input: expression = "a * b * c + b * a * c * 4", evalvars = [], evalints = [] Output: ["5*a*b*c"] Input: expression = "((a - b) * (b - c) + (c - a)) * ((a - b) + (b - c) * (c - a))", evalvars = [], evalints = [] Output: ["-1*a*a*b*b","2*a*a*b*c","-1*a*a*c*c","1*a*b*b*b","-1*a*b*b*c","-1*a*b*c*c","1*a*c*c*c","-1*b*b*b*c","2*b*b*c*c","-1*b*c*c*c","2*a*a*b","-2*a*a*c","-2*a*b*b","2*a*c*c","1*b*b*b","-1*b*b*c","1*b*c*c","-1*c*c*c","-1*a*a","1*a*b","1*a*c","-1*b*c"]
Note:
expression
will have length in range[1, 250]
.evalvars, evalints
will have equal lengths in range[0, 100]
.
解题思路:这个题目的思路其实很简单,只是实现较为复杂。因为变量可能有确定的值,也可能没有,而且最后的输出对格式的要求很严格,因此我们考虑在计算的途中不进行变量值的代入,而在最后进行变量值代入和格式整理。按照这个思路,计算过程就十分简单了,计算顺序与简单的计算器相同,用一个栈存储计算符号,用另一个栈存储操作数:
遇到+或-时:计算符号栈中存储所有计算操作,如果符号栈中存在“(”,则仅计算到“(”之前的
遇到*时:计算符号栈中存储在栈顶的*(如果有的话)
遇到“(”:直接存入符号栈
遇到“)”:计算“(”之前的所有计算操作,并弹出“(”
遇到操作数:直接存入栈
这里,由于存在变量,因此使用List<String>来存储每一次计算的结果,用TreeMap<String,Integer>来存储表达式和其系数
class Solution {
Map<String, Integer> eva;
public List<String> basicCalculatorIV(String expression, String[] evalvars, int[] evalints) {
//整理输入格式
List<String> input = getInput(expression);
eva = new HashMap<String, Integer>();
for(int i = 0; i < evalvars.length; i++){
eva.put(evalvars[i], evalints[i]);
}
//System.out.println(input.toString());
//循环处理所有输入,不进行计算和代入
Stack<List<String>> val = new Stack<List<String>>();
Stack<String> ope = new Stack<String>();
for(String str : input){
if(str.equals("(")){
ope.add(str);
}
else if(str.equals(")")){
while(!ope.peek().equals("(")){
List<String> b = val.pop();
List<String> a = val.pop();
String x = ope.pop();
val.push(operate(a, b, x));
}
ope.pop();
}
else if(str.equals("+")){
while(!ope.isEmpty() && !ope.peek().equals("(")){
List<String> b = val.pop();
List<String> a = val.pop();
String x = ope.pop();
val.push(operate(a, b, x));
}
ope.push("+");
}
else if(str.equals("-")){
while(!ope.isEmpty() && !ope.peek().equals("(")){
List<String> b = val.pop();
List<String> a = val.pop();
String x = ope.pop();
val.push(operate(a, b, x));
}
ope.push("-");
}
else if(str.equals("*")){
while(!ope.isEmpty() && ope.peek().equals("*")){
List<String> b = val.pop();
List<String> a = val.pop();
String x = ope.pop();
val.push(operate(a, b, x));
}
ope.push("*");
}
else{
List<String> list = new ArrayList<String>();
list.add(str);
val.push(list);
}
}
while(!ope.isEmpty()){
List<String> b = val.pop();
List<String> a = val.pop();
String x = ope.pop();
val.push(operate(a, b, x));
}
List<String> list = val.pop();
//System.out.println(list.toString());
//list中存储了所有的表达式,接下来需要将表达式化简
Map<String, Integer> map = new TreeMap<String, Integer>();
for(String str : list){
simple(map, str);
}
int max = 0;
for(String key : map.keySet())
max = Math.max(max, findDegree(key));
List<String> res = new ArrayList<String>();
for(int i = max; i > -1; i--){
for(String key : map.keySet()){
if(map.get(key) != 0 && findDegree(key) == i){
if(key.length() > 0)
res.add(map.get(key) + "*" + key);
else
res.add(map.get(key) + "");
}
}
}
return res;
}
public List<String> getInput(String expression){
String[] strs = expression.split(" ");
List<String> input = new ArrayList<String>();
for(String str : strs){
//System.out.println(str);
int front = 0, temp = str.indexOf('(');
while(temp != -1){
input.add("(");
front = temp + 1;
temp = str.indexOf('(', temp + 1);
}
temp = str.indexOf(")");
if(temp == -1)
input.add(str.substring(front));
else
input.add(str.substring(front, temp));
while(temp != -1){
input.add(")");
temp = str.indexOf(')', temp + 1);
}
}
return input;
}
public List<String> operate(List<String> a, List<String> b, String x){
if(x.equals("+")){
for(String str : b)
a.add(str);
return a;
}
if(x.equals("-")){
for(String str : b)
a.add("-" + str);
return a;
}
if(x.equals("*")){
List<String> res = new ArrayList<String>();
for(String m : a){
for(String n : b){
res.add(m + "*" + n);
}
}
return res;
}
System.out.println(x + " " + "Some thing wrong!");
return null;
}
public void simple(Map<String, Integer> map, String exp){
char[] chs = exp.toCharArray();
for(int i = 0; i < chs.length; i++){
if(chs[i] == '*')
chs[i] = ' ';
}
exp = new String(chs);
String[] strs = exp.split(" ");
boolean flag = true;
List<String> list = new ArrayList<String>();
int coefficient = 1;
for(String str : strs){
while(str.startsWith("-")){
flag = !flag;
str = str.substring(1);
}
if(isNum(str)){
coefficient *= toInt(str);
}
else{
list.add(str);
}
}
String temp = "";
Collections.sort(list);
for(String it : list)
temp += "*" + it;
if(temp.length() > 0)
temp = temp.substring(1);
if(!flag)
coefficient *= -1;
if(map.containsKey(temp))
map.put(temp, map.get(temp) + coefficient);
else
map.put(temp, coefficient);
}
public boolean isNum(String str){
if(eva.containsKey(str))
return true;
for(char ch : str.toCharArray()){
if(ch < '0' || ch > '9')
return false;
}
return true;
}
public int toInt(String str){
if(eva.containsKey(str))
return eva.get(str);
return Integer.parseInt(str);
}
public int findDegree(String str){
if(str.length() == 0)
return 0;
int res = 1;
int pos = str.indexOf("*");
while(pos != -1){
res++;
pos = str.indexOf("*", pos + 1);
}
return res;
}
}