此题真可谓是练习编程语言的绝好材料 !


import java.util.*; class Solution {
class Item {
Map<String, Integer> vars = new TreeMap<>();
int k = 1; String tos() {
StringBuilder builder = new StringBuilder();
List<String> a = new ArrayList<>();
for (String i : vars.keySet()) {
for (int j = 0; j < vars.get(i); j++) {
a.add(i);
}
}
if (a.size() == 0) return "";
builder.append(a.get(0));
for (int i = 1; i < a.size(); i++) {
builder.append("*" + a.get(i));
}
return builder.toString();
} Item copy() {
Item it = new Item();
it.k = k;
for (Map.Entry<String, Integer> i : vars.entrySet()) {
it.vars.put(i.getKey(), i.getValue());
}
return it;
} Item mul(Item another) {
Item ans = new Item();
ans.k = k * another.k;
for (Map.Entry<String, Integer> i : vars.entrySet()) {
ans.vars.put(i.getKey(), i.getValue());
}
for (Map.Entry<String, Integer> i : another.vars.entrySet()) {
if (ans.vars.containsKey(i.getKey())) {
ans.vars.put(i.getKey(), ans.vars.get(i.getKey()) + i.getValue());
} else {
ans.vars.put(i.getKey(), i.getValue());
}
}
return ans;
} int getMi() {
int s = 0;
for (int x : vars.values()) {
s += x;
}
return s;
} Item render(Map<String, Integer> eval) {
Item j = new Item();
j.k = k;
for (Map.Entry<String, Integer> i : vars.entrySet()) {
if (eval.containsKey(i.getKey())) {
j.k *= Math.pow(eval.get(i.getKey()), i.getValue());
} else {
j.vars.put(i.getKey(), i.getValue());
}
}
return j;
}
} class Exp {
List<Item> items = new ArrayList<>(); Exp add(Exp another) {
Exp exp = new Exp();
Map<String, Item> ma = new TreeMap<>();
for (Item i : another.items) {
Item j = i.copy();
exp.items.add(j);
ma.put(j.tos(), j);
}
for (Item i : items) {
String k = i.tos();
if (ma.containsKey(k)) {
ma.get(k).k += i.k;
} else {
Item j = i.copy();
ma.put(k, j);
exp.items.add(j);
}
}
return exp;
} Exp sub(Exp another) {
another.mul(-1);
Exp ans = add(another);
another.mul(-1);
ans.mul(-1);
return ans;
} void mul(int x) {
for (Item i : items) {
i.k *= x;
}
} Exp mul(Exp another) {
Exp ans = new Exp();
for (Item i : items) {
for (Item j : another.items) {
ans.items.add(i.mul(j));
}
}
return ans;
} @Override
public String toString() {
List<String> a = tos(this);
StringBuilder builder = new StringBuilder();
for (String i : a) {
builder.append("+" + i);
}
return builder.toString();
}
} List<String> tokenize(String expression) {
List<String> ans = new ArrayList<>();
for (int i = 0; i < expression.length(); i++) {
if ("()+-*".indexOf(expression.charAt(i)) != -1) {
ans.add(expression.charAt(i) + "");
} else if (Character.isDigit(expression.charAt(i))) {
int j = i;
while (j < expression.length() && Character.isDigit(expression.charAt(j))) {
j++;
}
ans.add(expression.substring(i, j));
i = j - 1;
} else if (Character.isLetter(expression.charAt(i))) {
int j = i;
while (j < expression.length() && Character.isLetter(expression.charAt(j))) {
j++;
}
ans.add(expression.substring(i, j));
i = j - 1;
}
}
return ans;
} int getPriority(String i) {
if (i.equals("*")) return 1;
if (i.equals("+") || i.equals("-")) return 0;
if (i.equals("(")) return 2;
if (i.equals(")")) return -1;
throw new RuntimeException("无法操作符号" + i);
} boolean isNumber(String s) {
for (int i = 0; i < s.length(); i++) {
if (!Character.isDigit(s.charAt(i))) {
return false;
}
}
return true;
} Exp number2Exp(int x) {
Exp exp = new Exp();
Item it = new Item();
it.k = x;
exp.items.add(it);
return exp;
} Exp var2Exp(String var) {
Exp exp = new Exp();
Item it = new Item();
it.vars.put(var, 1);
exp.items.add(it);
return exp;
} Exp calculate(Exp m, Exp n, String op) {
if (op.equals("*")) return m.mul(n);
else if (op.equals("+")) return m.add(n);
else if (op.equals("-")) return m.sub(n);
throw new RuntimeException("无法处理" + op + "运算");
} Exp parse(List<String> token) {
Stack<Exp> num = new Stack<>();
Stack<String> op = new Stack<>();
for (String i : token) {
if (i.equals(")")) {
while (!op.peek().equals("(")) {
num.push(calculate(num.pop(), num.pop(), op.pop()));
}
op.pop();
} else if ("+-*(".indexOf(i.charAt(0)) != -1) {
while (!op.empty() && !op.peek().equals("(") && getPriority(i) <= getPriority(op.peek())) {
Exp a = num.pop(), b = num.pop();
String o = op.pop();
num.push(calculate(a, b, o));
}
op.push(i);
} else if (isNumber(i)) {
num.push(number2Exp(Integer.parseInt(i)));
} else {
num.push(var2Exp(i));
}
}
while (!op.empty()) {
num.push(calculate(num.pop(), num.pop(), op.pop()));
}
return num.pop();
} Exp render(Exp exp, Map<String, Integer> eval) {
Exp ans = new Exp();
for (Item i : exp.items) {
Item j = i.render(eval);
ans.items.add(j);
}
return ans;
} Exp sort(Exp exp) {
//合并同类项
Map<String, Item> vars = new TreeMap<>();
for (Item i : exp.items) {
if (vars.containsKey(i.tos())) {
vars.get(i.tos()).k += i.k;
} else {
vars.put(i.tos(), i);
}
}
//去掉0项
exp.items = new ArrayList<>();
for (Item i : vars.values()) {
if (i.k == 0) continue;
exp.items.add(i);
}
//排序
exp.items.sort((o1, o2) -> {
int mi1 = o1.getMi();
int mi2 = o2.getMi();
if (mi1 == mi2) {
return o1.tos().compareTo(o2.tos());
} else {
return mi2 - mi1;
}
});
return exp;
} List<String> tos(Exp exp) {
List<String> ans = new ArrayList<>();
for (Item i : exp.items) {
String it = i.k + "";
if (i.tos().length() > 0) {
it += "*" + i.tos();
}
ans.add(it);
}
return ans;
} public List<String> basicCalculatorIV(String expression, String[] evalvars, int[] evalints) {
List<String> token = tokenize(expression);
Map<String, Integer> eval = new TreeMap<>();
for (int i = 0; i < evalvars.length; i++) {
eval.put(evalvars[i], evalints[i]);
}
Exp exp = parse(token);
exp = render(exp, eval);
exp = sort(exp);
List<String> ans = tos(exp);
return ans;
} void haha() {
List<String> ans = basicCalculatorIV("a*b+a*b*c*d", new String[]{"b"}, new int[]{2});
for (String i : ans) {
System.out.print(i + " ");
}
} public static void main(String[] args) {
Solution s = new Solution();
s.haha();
}
}

leetcode770. Basic Calculator IV的更多相关文章

  1. [LeetCode] Basic Calculator IV 基本计算器之四

    Given an expression such as expression = "e + 8 - a + 5" and an evaluation map such as {&q ...

  2. [Swift]LeetCode770. 基本计算器 IV | Basic Calculator IV

    Given an expression such as expression = "e + 8 - a + 5" and an evaluation map such as {&q ...

  3. 770. Basic Calculator IV

    Given an expression such as expression = "e + 8 - a + 5" and an evaluation map such as {&q ...

  4. [LeetCode] Basic Calculator 基本计算器

    Implement a basic calculator to evaluate a simple expression string. The expression string may conta ...

  5. [LeetCode] Basic Calculator III 基本计算器之三

    Implement a basic calculator to evaluate a simple expression string. The expression string may conta ...

  6. 224. Basic Calculator + 227. Basic Calculator II

    ▶ 两个四则表达式运算的题目,第 770 题 Basic Calculator IV 带符号计算不会做 Orz,第 772 题 Basic Calculator III 要收费 Orz. ▶ 自己的全 ...

  7. [LeetCode] 772. Basic Calculator III 基本计算器之三

    Implement a basic calculator to evaluate a simple expression string. The expression string may conta ...

  8. [LeetCode] Basic Calculator II 基本计算器之二

    Implement a basic calculator to evaluate a simple expression string. The expression string contains ...

  9. Basic Calculator II

    Implement a basic calculator to evaluate a simple expression string. The expression string contains ...

随机推荐

  1. python机器学习sklearn 岭回归(Ridge、RidgeCV)

    1.介绍 Ridge 回归通过对系数的大小施加惩罚来解决 普通最小二乘法 的一些问题. 岭系数最小化的是带罚项的残差平方和, 其中,α≥0α≥0 是控制系数收缩量的复杂性参数: αα 的值越大,收缩量 ...

  2. SSE,MSE,RMSE,R-square指标讲解

    SSE(和方差.误差平方和):The sum of squares due to errorMSE(均方差.方差):Mean squared errorRMSE(均方根.标准差):Root mean ...

  3. 如何三招帮你排查Linux中的硬件问题

    下列贴士帮助你更快速更轻松地为Linux中的硬件排查故障.许多不同的因素可能导致Linux硬件出现问题:在你开始尝试诊断之前,了解最常见的问题以及最有可能找到原因的环节是明智之举. Linux服务器在 ...

  4. Docker container常用命令

    列出所有的container. docker container ls 启动一个container. docker run –p <host端口>: <container端口> ...

  5. 纪念google reader

    2013年3月14日早上,谷歌在其官方博客宣布,2005年推出的 Google Reader 将在7月1号关闭. google reader的历史 以下搞自维基百科http://zh.wikipedi ...

  6. LintCode: Fizz Buzz

    C++ class Solution { public: /** * param n: As description. * return: A list of strings. */ vector&l ...

  7. 1050: 贝贝的ISBN号码(isbn)

    #include <iostream> #include <iomanip> #include <cstdlib> #include <string> ...

  8. linux2.6.30.4内核移植(3)——yaffs文件系统移植

    内核源码:linux2.6.30.4 交叉编译工具:3.4.5 移植linux内核至:TQ2440 工作基础:http://www.cnblogs.com/nufangrensheng/p/36696 ...

  9. JAVA GC优化入门

    为什么需要优化GC? JAVA的GC是面试必考的题目,可是在实际项目中什么时候使用GC哪?或者应该什么时候优化GC哪?有句名言:“GC优化永远是最后一项任务”. 在使用GC之前,应该考虑一下进行GC的 ...

  10. 转:nginx基础概念(connection)

    在nginx中connection就是对tcp连接的封装,其中包括连接的socket,读事件,写事件.利用nginx封装的connection,我们可以很方便的使用nginx来处理与连接相关的事情,比 ...