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


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. 汉字转拼音 pinyin4j 字符串 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  2. 【Javascript设计模式1】-单例模式

    <parctical common lisp>的作者曾说,如果你需要一种模式,那一定是哪里出了问题.他所说的问题是指因为语言的天生缺陷,不得不去寻求和总结一种通用的解决方案. 不管是弱类型 ...

  3. 以快板之名说Android 应用程序电源管理

    当里个当,当里个当.Android开发UE(用户体验)为导向,首要任务便是省电量. 当里个当,当里个当.有一设备立足于墙边,这个设备唤固定电话.你的app造成这样,用户很快把你弃墙角.你咆哮耗电奈何与 ...

  4. Linux下逻辑地址-线性地址-物理地址图解(转)

    一.逻辑地址转线性地址 机器语言指令中出现的内存地址,都是逻辑地址,需要转换成线性地址,再经过MMU(CPU中的内存管理单元)转换成物理地址才能够被访问到. 我们写个最简单的hello world程序 ...

  5. RAMPS1.4 3d打印控制板接线与测试5

    切片软件是生产打印机主控板可以识别的代码(Gcode)的工具,没有这个软件的帮忙,打印机不能识别3d模型文件.这里暂时只介绍Slic3r这个切片软件.简单好用功能强大. 1.打开expert模式 Sl ...

  6. [Canvas]人物型英雄出现(前作仅为箭头)

    源码点此下载,用浏览器打开index.html观看. 代码: <!DOCTYPE html> <html lang="utf-8"> <meta ht ...

  7. TCP/IP, UDP, ICMP, ARP协议族简介--纯图慎点

    ISO/OSI的网络模型架构 TCP/IP参考模型的层次结果 以太网头部结构 以太网属于数据链路层, 属于最基本的协议结构 IP协议 IP协议为TCP, UDP, ICMP提供最基本的数据传输通路 I ...

  8. git 保存用户名密码

    打开本地的.git/config 加入 [credential] helper = store 保存,第一次需要输入用户名密码,输入一次密码后第二次就会记住密码了不会再提示输入用户名及密码

  9. 跟我学AngularJS:全局变量设置之value vs constant vs rootscope vs 服务[转]

    林炳文Evankaka原创作品.转载请注明出处http://blog.csdn.net/evankaka 摘要:本文要讲讲Angular中value vs. constant以及全局变量的设置 本教程 ...

  10. Maven的JAR包仓库,不用再百度搜JAR包了!

    http://search.maven.org/ 今天初学Maven,发现Maven的中央仓库里差点儿什么jar都有...........还有各种版本号... 你值得拥有!