Approach
Stack-based processing
For Basic Calculator IV, the implementation keeps unresolved items in last-in, first-out order, often to match boundaries, parse structure, or maintain monotonic candidates.
- Define what every stack entry represents.
- Pop entries once the current item resolves or invalidates them.
- Push the current item with only the information later steps need.
Code notes
- 183 lines of Java from the credited upstream file 770.java.
- The implementation visibly relies on sequence storage, hash lookup, ordered lookup, work queue.
- 17 loop blocks detected.
Complexity
If each item is pushed and popped at most once, the stack work is linear.
Check the problem constraints before deciding whether this complexity will pass.
Use this to learn the idea, then write your own version.
1class Poly {2 public Poly add(Poly o) {3 for (final String term : o.terms.keySet())4 terms.merge(term, o.terms.get(term), Integer::sum);5 return this;6 }7 8 public Poly minus(Poly o) {9 for (final String term : o.terms.keySet())10 terms.merge(term, -o.terms.get(term), Integer::sum);11 return this;12 }13 14 public Poly mult(Poly o) {15 Poly res = new Poly();16 for (final String a : terms.keySet())17 for (final String b : o.terms.keySet())18 res.terms.merge(merge(a, b), terms.get(a) * o.terms.get(b), Integer::sum);19 return res;20 }21 22 23 24 25 26 27 28 29 30 31 32 public List<String> toList() {33 List<String> res = new ArrayList<>();34 List<String> keys = new ArrayList<>(terms.keySet());35 Collections.sort(keys, new Comparator<String>() {36 @Override37 public int compare(final String a, final String b) {38 39 if (a.equals("1"))40 return 1;41 if (b.equals("1"))42 return -1;43 String[] as = a.split("\\*");44 String[] bs = b.split("\\*");45 46 47 return as.length == bs.length ? a.compareTo(b) : bs.length - as.length;48 }49 });50 for (final String key : keys)51 if (terms.get(key) != 0)52 res.add(concat(key));53 return res;54 }55 56 public Poly() {}57 public Poly(final String term, int coef) {58 terms.put(term, coef);59 }60 61 private Map<String, Integer> terms = new HashMap<>();62 63 64 private static String merge(final String a, final String b) {65 if (a.equals("1"))66 return b;67 if (b.equals("1"))68 return a;69 StringBuilder sb = new StringBuilder();70 String[] A = a.split("\\*");71 String[] B = b.split("\\*");72 int i = 0; 73 int j = 0; 74 while (i < A.length && j < B.length)75 if (A[i].compareTo(B[j]) < 0)76 sb.append("*").append(A[i++]);77 else78 sb.append("*").append(B[j++]);79 while (i < A.length)80 sb.append("*").append(A[i++]);81 while (j < B.length)82 sb.append("*").append(B[j++]);83 return sb.substring(1).toString();84 }85 86 private String concat(final String term) {87 if (term.equals("1"))88 return String.valueOf(terms.get(term));89 return new StringBuilder().append(terms.get(term)).append('*').append(term).toString();90 }91}92 93class Solution {94 public List<String> basicCalculatorIV(String expression, String[] evalvars, int[] evalints) {95 List<String> tokens = getTokens(expression);96 Map<String, Integer> evalMap = new HashMap<>();97 98 for (int i = 0; i < evalvars.length; ++i)99 evalMap.put(evalvars[i], evalints[i]);100 101 for (int i = 0; i < tokens.size(); ++i)102 if (evalMap.containsKey(tokens.get(i)))103 tokens.set(i, String.valueOf(evalMap.get(tokens.get(i))));104 105 List<String> postfix = infixToPostfix(tokens);106 return evaluate(postfix).toList();107 }108 109 private List<String> getTokens(final String s) {110 List<String> tokens = new ArrayList<>();111 int i = 0;112 for (int j = 0; j < s.length(); ++j)113 if (s.charAt(j) == ' ') {114 if (i < j)115 tokens.add(s.substring(i, j));116 i = j + 1;117 } else if ("()+-*".contains(s.substring(j, j + 1))) {118 if (i < j)119 tokens.add(s.substring(i, j));120 tokens.add(s.substring(j, j + 1));121 i = j + 1;122 }123 if (i < s.length())124 tokens.add(s.substring(i));125 return tokens;126 }127 128 private boolean isOperator(final String token) {129 return token.equals("+") || token.equals("-") || token.equals("*");130 }131 132 private boolean precedes(final String prevOp, final String currOp) {133 if (prevOp.equals("("))134 return false;135 return prevOp.equals("*") || currOp.equals("+") || currOp.equals("-");136 }137 138 private List<String> infixToPostfix(List<String> tokens) {139 List<String> postfix = new ArrayList<>();140 Deque<String> ops = new ArrayDeque<>();141 142 for (final String token : tokens)143 if (token.equals("(")) {144 ops.push(token);145 } else if (token.equals(")")) {146 while (!ops.peek().equals("("))147 postfix.add(ops.pop());148 ops.pop();149 } else if (isOperator(token)) {150 while (!ops.isEmpty() && precedes(ops.peek(), token))151 postfix.add(ops.pop());152 ops.push(token);153 } else { 154 postfix.add(token);155 }156 157 while (!ops.isEmpty())158 postfix.add(ops.pop());159 160 return postfix;161 }162 163 private Poly evaluate(List<String> postfix) {164 LinkedList<Poly> polys = new LinkedList<>();165 for (final String token : postfix)166 if (isOperator(token)) {167 final Poly b = polys.removeLast();168 final Poly a = polys.removeLast();169 if (token.equals("+"))170 polys.add(a.add(b));171 else if (token.equals("-"))172 polys.add(a.minus(b));173 else 174 polys.add(a.mult(b));175 } else if (token.charAt(0) == '-' || token.chars().allMatch(c -> Character.isDigit(c))) {176 polys.add(new Poly("1", Integer.parseInt(token)));177 } else {178 polys.add(new Poly(token, 1));179 }180 return polys.getFirst();181 }182}183