|
| 1 | +/** |
| 2 | + * @param {string} s |
| 3 | + * @return {number} |
| 4 | + */ |
| 5 | +const calculate = function ( |
| 6 | + s, |
| 7 | + start = 0, |
| 8 | + end = s.length, |
| 9 | + parentheses = findParentheses(s) |
| 10 | +) { |
| 11 | + const stack = [] |
| 12 | + let op = '+' |
| 13 | + let num = 0 |
| 14 | + for (let i = start; i < end; i++) { |
| 15 | + const c = s[i] |
| 16 | + if (/[0-9]+/.test(c)) { |
| 17 | + const n = parseInt(c) |
| 18 | + num = 10 * num + n |
| 19 | + } else if (isOperator(c)) { |
| 20 | + compute(op, stack, num) |
| 21 | + op = c |
| 22 | + num = 0 |
| 23 | + } else if (c === '(') { |
| 24 | + num = calculate(s, i + 1, parentheses[i], parentheses) |
| 25 | + i = parentheses[i] |
| 26 | + } |
| 27 | + } |
| 28 | + compute(op, stack, num) |
| 29 | + return stack.reduce((acc, cur) => acc + cur, 0) |
| 30 | +} |
| 31 | + |
| 32 | +function findParentheses(s) { |
| 33 | + const map = {} |
| 34 | + const stack = [] |
| 35 | + for (let i = 0; i < s.length; i++) { |
| 36 | + if (s[i] === '(') { |
| 37 | + stack.push(i) |
| 38 | + } else if (s[i] === ')') { |
| 39 | + map[stack.pop()] = i |
| 40 | + } |
| 41 | + } |
| 42 | + return map |
| 43 | +} |
| 44 | + |
| 45 | +function compute(op, stack, num) { |
| 46 | + if (op === '-') { |
| 47 | + stack.push(-num) |
| 48 | + } else if (op === '+') { |
| 49 | + stack.push(num) |
| 50 | + } else if (op === '*') { |
| 51 | + stack.push(stack.pop() * num) |
| 52 | + } else if (op === '/') { |
| 53 | + const pre = stack.pop() |
| 54 | + const sign = pre / num >= 0 ? 1 : -1 |
| 55 | + const val = Math.floor(Math.abs(pre / num)) |
| 56 | + stack.push(Math.floor(sign * val)) |
| 57 | + } |
| 58 | +} |
| 59 | + |
| 60 | +function isOperator(c) { |
| 61 | + return c === '+' || c === '-' || c === '*' || c === '/' |
| 62 | +} |
0 commit comments