224. 基本计算器
思路
做这题的时候,我想起了当时上编译原理的词法分析。于是想到是否可以使用栈来模拟,其中一个栈用来模拟括号的处理,另一个栈用来模拟单个括号内的计算处理。如第一个代码所示。但是我这个做法比官解的做法慢了很多。因为需要频繁地构建字符串,并且把字符串从一个栈转到另一个栈,时间复杂度的常数较大。
为了解决上述的问题,我们分别用数字栈和运算符栈来模拟操作。其余思路接近。
小tips
单目负号运算符的处理
单目负号运算符当且仅当负号前没有数字时出现,为了统一运算,我们可以把其视为0-x,因此,我们在其前方加入0即可。
同时,为了防止第一个数为负数,我们往数字栈里第一个数插入0。这类似于哨兵的思想。
Java判断字符是否为数字
Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| class Solution { Deque<String> parentheses = new LinkedList<>(); Deque<String> cal = new LinkedList<>(); public int calculate(String s) { char[] cs = s.toCharArray(); int n = cs.length; for (int i = 0; i < n; i++) { if (cs[i] == ' ') continue; if (cs[i] == ')') util(); else if ("(+-".indexOf(cs[i]) >= 0) { parentheses.push(String.valueOf(cs[i])); } else { StringBuilder sb = new StringBuilder(); while (i < n && "0123456789".indexOf(cs[i]) >= 0) { sb.append(cs[i++]); } i--; parentheses.push(sb.toString()); } } if (parentheses.size() > 1) util(); return Integer.valueOf(parentheses.pop()); }
void util() { while(!parentheses.isEmpty()) { String top = parentheses.pop(); if (top.equals("(")) break; cal.push(top); } while (cal.size() > 1) { if (cal.peek().equals("-")) { cal.pop(); cal.push(String.valueOf(-Integer.valueOf(cal.pop()))); continue; } int left = Integer.valueOf(cal.pop()); String op = cal.pop(); int right = Integer.valueOf(cal.pop()); int next = 0; if (op.equals("+")) { next = left + right; } else { next = left - right; } cal.push(String.valueOf(next)); } parentheses.push(cal.pop()); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
| class Solution { public int calculate(String s) { Deque<Integer> nums = new ArrayDeque<>(); nums.push(0); s = s.replaceAll(" ", ""); Deque<Character> ops = new ArrayDeque<>(); int n = s.length(); char[] cs = s.toCharArray(); for (int i = 0; i < n; i++) { char c = cs[i]; if (c == '(') { ops.push(c); } else if (c == ')') { if (ops.peek() != '(') { calc(nums, ops); } ops.pop(); } else { if (isNum(c)) { int u = 0; int j = i; while (j < n && isNum(cs[j])) u = u * 10 + (int)(cs[j++] - '0'); nums.push(u); i = j - 1; } else { if (i > 0 && (cs[i - 1] == '(' || cs[i - 1] == '+' || cs[i - 1] == '-')) { nums.push(0); } while (!ops.isEmpty() && ops.peek() != '(') calc(nums, ops); ops.push(c); } } } if (!ops.isEmpty()) calc(nums, ops); return nums.peek(); } void calc(Deque<Integer> nums, Deque<Character> ops) { if (ops.isEmpty()) return; int b = nums.pop(), a = nums.pop(); char op = ops.pop(); nums.push(op == '+' ? a + b : a - b); } boolean isNum(char c) { return Character.isDigit(c); } }
|