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
- 197 lines of C++ from the credited upstream file 770.cpp.
- The implementation visibly relies on sequence storage, hash lookup.
- 19 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 friend Poly operator+(const Poly& lhs, const Poly& rhs) {3 Poly res(lhs);4 for (const auto& [term, coef] : rhs.terms)5 res.terms[term] += coef;6 return res;7 }8 9 friend Poly operator-(const Poly& lhs, const Poly& rhs) {10 Poly res(lhs);11 for (const auto& [term, coef] : rhs.terms)12 res.terms[term] -= coef;13 return res;14 }15 16 friend Poly operator*(const Poly& lhs, const Poly& rhs) {17 Poly res;18 for (const auto& [a, aCoef] : lhs.terms)19 for (const auto& [b, bCoef] : rhs.terms)20 res.terms[merge(a, b)] += aCoef * bCoef;21 return res;22 }23 24 25 26 27 28 29 30 31 32 public:33 vector<string> toList() {34 vector<string> res;35 vector<string> keys;36 for (const auto& [term, _] : terms)37 keys.push_back(term);38 ranges::sort(keys, [&](const string& a, const string& b) {39 40 if (a == "1")41 return false;42 if (b == "1")43 return true;44 const vector<string> as = split(a, '*');45 const vector<string> bs = split(b, '*');46 47 48 return as.size() == bs.size() ? a < b : as.size() > bs.size();49 });50 auto concat = [&](const string& term) -> string {51 if (term == "1")52 return to_string(terms[term]);53 return to_string(terms[term]) + '*' + term;54 };55 for (const string& key : keys)56 if (terms[key])57 res.push_back(concat(key));58 return res;59 }60 61 Poly() = default;62 Poly(const string& term, int coef) {63 terms[term] = coef;64 }65 66 private:67 unordered_map<string, int> terms;68 69 70 static string merge(const string& a, const string& b) {71 if (a == "1")72 return b;73 if (b == "1")74 return a;75 string res;76 vector<string> A = split(a, '*');77 vector<string> B = split(b, '*');78 int i = 0; 79 int j = 0; 80 while (i < A.size() && j < B.size())81 if (A[i] < B[j])82 res += '*' + A[i++];83 else84 res += '*' + B[j++];85 while (i < A.size())86 res += '*' + A[i++];87 while (j < B.size())88 res += '*' + B[j++];89 return res.substr(1);90 }91 92 static vector<string> split(const string& token, char c) {93 vector<string> vars;94 istringstream iss(token);95 for (string var; getline(iss, var, c);)96 vars.push_back(var);97 return vars;98 }99};100 101class Solution {102 public:103 vector<string> basicCalculatorIV(string expression, vector<string>& evalvars,104 vector<int>& evalints) {105 vector<string> tokens = getTokens(expression);106 unordered_map<string, int> evalMap;107 108 for (int i = 0; i < evalvars.size(); ++i)109 evalMap[evalvars[i]] = evalints[i];110 111 for (string& token : tokens)112 if (const auto it = evalMap.find(token); it != evalMap.cend())113 token = to_string(it->second);114 115 const vector<string>& postfix = infixToPostfix(tokens);116 return evaluate(postfix).toList();117 }118 119 private:120 vector<string> getTokens(const string& s) {121 vector<string> tokens;122 int i = 0;123 for (int j = 0; j < s.length(); ++j)124 if (s[j] == ' ') {125 if (i < j)126 tokens.push_back(s.substr(i, j - i));127 i = j + 1;128 } else if (string("()+-*").find(s[j]) != string::npos) {129 if (i < j)130 tokens.push_back(s.substr(i, j - i));131 tokens.push_back(s.substr(j, 1));132 i = j + 1;133 }134 if (i < s.length())135 tokens.push_back(s.substr(i));136 return tokens;137 }138 139 bool isOperator(const string& token) {140 return token == "+" || token == "-" || token == "*";141 }142 143 vector<string> infixToPostfix(const vector<string>& tokens) {144 vector<string> postfix;145 stack<string> ops;146 147 auto precedes = [](const string& prevOp, const string& currOp) -> bool {148 if (prevOp == "(")149 return false;150 return prevOp == "*" || currOp == "+" || currOp == "-";151 };152 153 for (const string& token : tokens)154 if (token == "(") {155 ops.push(token);156 } else if (token == ")") {157 while (ops.top() != "(")158 postfix.push_back(ops.top()), ops.pop();159 ops.pop();160 } else if (isOperator(token)) {161 while (!ops.empty() && precedes(ops.top(), token))162 postfix.push_back(ops.top()), ops.pop();163 ops.push(token);164 } else { 165 postfix.push_back(token);166 }167 168 while (!ops.empty())169 postfix.push_back(ops.top()), ops.pop();170 171 return postfix;172 }173 174 Poly evaluate(const vector<string>& postfix) {175 vector<Poly> polys;176 for (const string& token : postfix)177 if (isOperator(token)) {178 const Poly b = polys.back();179 polys.pop_back();180 const Poly a = polys.back();181 polys.pop_back();182 if (token == "+")183 polys.push_back(a + b);184 else if (token == "-")185 polys.push_back(a - b);186 else 187 polys.push_back(a * b);188 } else if (token[0] == '-' ||189 ranges::all_of(token, [](char c) { return isdigit(c); })) {190 polys.push_back(Poly("1", stoi(token)));191 } else {192 polys.push_back(Poly(token, 1));193 }194 return polys[0];195 }196};197