diff --git a/src/main/java/g0701_0800/s0770_basic_calculator_iv/Solution.java b/src/main/java/g0701_0800/s0770_basic_calculator_iv/Solution.java index 15e2fb65c..03fd947c5 100644 --- a/src/main/java/g0701_0800/s0770_basic_calculator_iv/Solution.java +++ b/src/main/java/g0701_0800/s0770_basic_calculator_iv/Solution.java @@ -1,193 +1,182 @@ package g0701_0800.s0770_basic_calculator_iv; // #Hard #String #Hash_Table #Math #Stack #Recursion -// #2022_04_30_Time_8_ms_(96.92%)_Space_42.9_MB_(93.85%) +// #2025_04_17_Time_8_ms_(95.70%)_Space_45.18_MB_(49.46%) import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.TreeMap; public class Solution { - private static class Result { - private Map, Integer> map; + private String s; + private char[] arr; + private int[] braces; + private final Map variables = new HashMap<>(); - Result() { - map = new HashMap<>(); - } - - Result(Map, Integer> map) { - this.map = map; - } - - void update(List key, int val) { - map.put(key, map.getOrDefault(key, 0) + val); - } - - Map, Integer> getMap() { - return map; - } - - List toList() { - List> keyList = new ArrayList<>(map.keySet()); - Map, String> list2String = new HashMap<>(); - for (List key : keyList) { - StringBuilder sb = new StringBuilder(); - for (String k : key) { - sb.append(k).append("*"); - } - list2String.put(key, sb.toString()); + public List basicCalculatorIV(String expression, String[] evalvars, int[] evalints) { + s = expression; + arr = s.toCharArray(); + int n = arr.length; + braces = new int[n]; + Arrays.fill(braces, -1); + int[] stack = new int[n / 2]; + int index = -1; + for (int i = 0; i < n; ++i) { + if (arr[i] == '(') { + stack[++index] = i; + } else if (arr[i] == ')') { + int last = stack[index--]; + braces[last] = i; + braces[i] = last; } - keyList.sort( - (a, b) -> - (a.size() == b.size() - ? list2String.get(a).compareTo(list2String.get(b)) - : b.size() - a.size())); - List res = new ArrayList<>(); - for (List key : keyList) { - if (map.get(key) == 0) { - continue; - } - StringBuilder sb = new StringBuilder(); - sb.append(map.get(key)); - for (String k : key) { - sb.append("*").append(k); + } + for (int i = 0; i < evalvars.length; ++i) { + variables.put(evalvars[i], evalints[i]); + } + List terms = dewIt(0, n - 1); + Map map = + new TreeMap<>( + new Comparator<>() { + public int compare(String a, String b) { + int ca = countStars(a); + int cb = countStars(b); + if (ca != cb) { + return cb - ca; + } else { + return a.compareTo(b); + } + } + + private int countStars(String s) { + int ans = 0; + for (char c : s.toCharArray()) { + if (c == '*') { + ++ans; + } + } + return ans; + } + }); + for (Term term : terms) { + if (term.coeff != 0) { + String key = term.getKey(); + if (map.containsKey(key)) { + int oldCoeff = map.get(key); + if (oldCoeff == -term.coeff) { + map.remove(key); + } else { + map.put(key, oldCoeff + term.coeff); + } + } else { + map.put(key, term.coeff); } - res.add(sb.toString()); } - return res; } - } - - private Map evalMap; - private int i = 0; - - public List basicCalculatorIV(String expression, String[] evalvars, int[] evalints) { - evalMap = new HashMap<>(); - for (int j = 0; j < evalvars.length; j++) { - evalMap.put(evalvars[j], evalints[j]); + List ans = new ArrayList<>(); + for (Map.Entry entry : map.entrySet()) { + ans.add(entry.getValue() + entry.getKey()); } - i = -1; - next(expression); - Result res = expression(expression); - return res.toList(); + return ans; } - private Result expression(String s) { - Result res = term(s); - while (i < s.length() && (s.charAt(i) == '+' || s.charAt(i) == '-')) { - int c = s.charAt(i); - next(s); - if (c == '+') { - res = add(res, term(s)); + private List dewIt(int a, int b) { + if (braces[a] == b) { + return dewIt(a + 1, b - 1); + } + List ans = new ArrayList<>(); + List buffer = new ArrayList<>(); + buffer.add(new Term(1, new ArrayList<>())); + int i = a; + while (i <= b) { + int j = i; + List curr; + if (arr[i] == '(') { + j = braces[i] + 1; + curr = dewIt(i + 1, j - 2); } else { - res = subtract(res, term(s)); + while (j <= b && arr[j] != ' ') { + ++j; + } + String exp = s.substring(i, j); + int val = 1; + List vars = new ArrayList<>(); + if (variables.containsKey(exp)) { + val = variables.get(exp); + } else if (exp.charAt(0) <= '9') { + val = Integer.parseInt(exp); + } else { + vars.add(exp); + } + curr = new ArrayList<>(); + curr.add(new Term(val, vars)); } + buffer = multiply(buffer, curr); + if (j > b || arr[j + 1] == '+' || arr[j + 1] == '-') { + ans.addAll(buffer); + buffer = new ArrayList<>(); + } + if (j < b) { + ++j; + if (arr[j] == '+') { + buffer.add(new Term(1, new ArrayList<>())); + } else if (arr[j] == '-') { + buffer.add(new Term(-1, new ArrayList<>())); + } + j += 2; + } + i = j; } - return res; - } - - private Result term(String s) { - Result res = factor(s); - while (i < s.length() && s.charAt(i) == '*') { - next(s); - res = multiply(res, factor(s)); - } - return res; + return ans; } - private Result multiply(Result r1, Result r2) { - Map, Integer> map1 = r1.getMap(); - Map, Integer> map2 = r2.getMap(); - Map, Integer> map = new HashMap<>(); - for (Map.Entry, Integer> entry1 : map1.entrySet()) { - for (Map.Entry, Integer> entry2 : map2.entrySet()) { - List key = new ArrayList<>(entry1.getKey()); - key.addAll(entry2.getKey()); - Collections.sort(key); - map.put(key, map.getOrDefault(key, 0) + entry1.getValue() * entry2.getValue()); + private List multiply(List a, List b) { + List ans = new ArrayList<>(); + for (Term x : a) { + for (Term y : b) { + Term prod = x.copy(); + prod.multiply(y); + ans.add(prod); } } - return new Result(map); + return ans; } - private Result add(Result r1, Result r2) { - Map, Integer> map1 = r1.getMap(); - Map, Integer> map2 = r2.getMap(); - Map, Integer> map = new HashMap<>(); - for (Map.Entry, Integer> entry1 : map1.entrySet()) { - map.put(entry1.getKey(), map.getOrDefault(entry1.getKey(), 0) + entry1.getValue()); - } - for (Map.Entry, Integer> entry2 : map2.entrySet()) { - map.put(entry2.getKey(), map.getOrDefault(entry2.getKey(), 0) + entry2.getValue()); - } - return new Result(map); - } + private static class Term { + int coeff; + List vars; - private Result subtract(Result r1, Result r2) { - Map, Integer> map1 = r1.getMap(); - Map, Integer> map2 = r2.getMap(); - Map, Integer> map = new HashMap<>(); - for (Map.Entry, Integer> entry1 : map1.entrySet()) { - map.put(entry1.getKey(), map.getOrDefault(entry1.getKey(), 0) + entry1.getValue()); - } - for (Map.Entry, Integer> entry2 : map2.entrySet()) { - map.put(entry2.getKey(), map.getOrDefault(entry2.getKey(), 0) - entry2.getValue()); + public Term(int a, List c) { + this.coeff = a; + vars = new ArrayList<>(); + vars.addAll(c); } - return new Result(map); - } - private Result factor(String s) { - Result res = new Result(); - if (s.charAt(i) == '(') { - next(s); - res = expression(s); - next(s); - return res; - } - if (Character.isLowerCase(s.charAt(i))) { - return identifier(s); + public String getKey() { + StringBuilder b = new StringBuilder(); + Collections.sort(vars); + for (String x : vars) { + b.append('*'); + b.append(x); + } + return b.toString(); } - res.update(new ArrayList<>(), number(s)); - return res; - } - private Result identifier(String s) { - Result res = new Result(); - StringBuilder sb = new StringBuilder(); - while (i < s.length() && Character.isLowerCase(s.charAt(i))) { - sb.append(s.charAt(i)); - i++; - } - i--; - next(s); - String variable = sb.toString(); - if (evalMap.containsKey(variable)) { - res.update(new ArrayList<>(), evalMap.get(variable)); - } else { - List key = new ArrayList<>(); - key.add(variable); - res.update(key, 1); - } - return res; - } - - private int number(String s) { - int res = 0; - while (i < s.length() && s.charAt(i) >= '0' && s.charAt(i) <= '9') { - res = res * 10 + (s.charAt(i) - '0'); - i++; + public void multiply(Term that) { + this.coeff *= that.coeff; + if (this.coeff == 0) { + vars.clear(); + } else { + this.vars.addAll(that.vars); + } } - i--; - next(s); - return res; - } - private void next(String s) { - i++; - while (i < s.length() && s.charAt(i) == ' ') { - i++; + public Term copy() { + return new Term(coeff, vars); } } }