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


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. ElasticSearch客户端注解使用介绍

    The best elasticsearch highlevel java rest api-----bboss 1.ElasticSearch客户端bboss提供了一系列注解 @ESId  用于标识 ...

  2. 测试数据——有效范围(2)

    测试数据库搞好,学习了一下逾期率的官方定义: • 对于某支标,如果某一期没有正常还款,则悲观逾期率=所有未还本金/借款本金: • 对于一批标,悲观逾期率=当前逾期标的所有未还本金/借款本金: • 以3 ...

  3. IIS 7.5: HOW TO ENABLE TLS 1.1 AND TLS 1.2

    In IIS 7.5, which is installed on Windows 2008 R2 servers, only SSL 3.0 and TLS 1.0 are enabled for ...

  4. Logcat用法初探

    首先定位到adb所在的目录 将手机连接上电脑. 在命令行运行: adb devices 这个命令可以列出所有连上的移动设备. 在命令行运行: adb logcat 可以显示日志.   以下是例子截图: ...

  5. 编译GSLSDevil的全过程

      GLSLDevil是调试OpenGL程序的工具. GLSLDevil的新版本已经改名为GLSL-Debugger, github的地址在这里:http://glsl-debugger.github ...

  6. 【指导】SonarQube 部署说明

    转载:https://blog.csdn.net/cuiaamay/article/details/52057091 1,安装 1.1 安装依赖 需要保证Oracle JRE 8 及以上,或者 Ope ...

  7. SuperMap开发入门2——环境部署

    由于超图的相关资源比较少,可参考官方提供的<SuperMap iDesktop 9D安装指南>和<SuperMap iObjects .NET 9D安装指南>完成应用软件和开发 ...

  8. Mysql数据库常用分库和分表方式

    http://blog.csdn.net/clevercode/article/details/50877580 1 分库 1.1 按照功能分库 按照功能进行分库.常见的分成6大库:    1 用户类 ...

  9. android中使用WebView请求本地网页

    使用WebView的方式请参考我的上一篇文章:android中使用WebView请求网页 这里说一下请求本地网页的方法: 本地网页应该把网页保存在src/main/assets目录下: webView ...

  10. vsphere storage appliance工作原理和实施

    摘录自:http://www.07net01.com/storage_networking/VMwarexunihuazhiVSA_vSphere_Storage_Appliance_qunji_yi ...