1+ // 224. 基本计算器
2+
3+
4+ /*
5+ 双栈:
6+ 1、使用两个栈,numsStack 存放数字,opsStack 存放操作符
7+ 2、预处理:
8+ 1)由于第一个数可能是负数,为了减少边界判断,先往 numsStack 添加一个 0
9+ 2)输入中不存在两个连续的操作符,为防止 () 内出现的首个字符为运算符,将所有空格去掉,将 (- 替换为 (0- ,(+ 替换为 (0+
10+ 3、遍历字符串中的字符
11+ 1)遇到 ( 时,则存入操作符栈
12+ 2)遇到 ) 时,
13+ ① 当操作符栈 不为空 且 栈顶不是左括号时,取出两个数字和操作符进行计算,并将计算结果存入数字栈
14+ ② 直到遇到左括号,从操作符栈 出栈
15+ 3)遇到数字时,继续遍历获取连续的数字,并将字符串转化成整型类型数字,最后数字存入数字栈
16+ 4)遇到操作符 +、- 时,
17+ ① 如果前一字符是左括号,要先将0存入数字栈,表示 (0- 或 (0+ ,才能进行计算
18+ ② 当操作符栈 不为空 且 栈顶不是左括号时,取出两个数字和操作符进行计算,并将计算结果存入数字栈
19+ ③ 将当前操作符存入 操作符栈
20+ 4、操作符栈仍不为空时,取出两个数字和操作符进行计算,并将计算结果存入数字栈,最终返回数字栈顶值
21+ 5、计算的时机:
22+ 1)当前字符为 ) ,操作符栈顶字符为 (,说明括号内的数字计算完了,可以结束了
23+ 当前字符为 +、- ,操作符栈顶字符为 (,说明括号内的数字只有一个,还不能计算
24+ 所以遇到 )、+、- 时,操作符栈 不为空 且 栈顶不是 ( 时才能计算
25+ 2)遇到 )、+、- 时,才会计算前一操作符的结果,然后将 (出操作符栈 或 +、-入操作符栈
26+ 3)字符串遍历完后,操作符栈会不为空,因为 遇到新的操作符才会计算旧的操作符 和 受到(的限制 导致前面的没有计算,但只剩 +、-,所以可以直接计算
27+ */
28+ class Solution {
29+ public int calculate (String s ) {
30+ Deque <Character > opsStack = new ArrayDeque <>();
31+ Deque <Integer > numsStack = new ArrayDeque <>();
32+ numsStack .push (0 );
33+ s = s .replaceAll (" " , "" );
34+ int n = s .length ();
35+ char [] charArray = s .toCharArray ();
36+ for (int i = 0 ; i < n ; i ++) {
37+ char c = charArray [i ];
38+ if (c == '(' ) {
39+ opsStack .push (c );
40+ } else if (c == ')' ) {
41+ while (!opsStack .isEmpty () && opsStack .peek () != '(' ) {
42+ cal (numsStack , opsStack );
43+ }
44+ opsStack .pop ();
45+ } else if (Character .isDigit (c )) {
46+ int j = i , num = 0 ;
47+ while (j < n && Character .isDigit (charArray [j ])) {
48+ num = num * 10 + charArray [j ++] - '0' ;
49+ }
50+ numsStack .push (num );
51+ i = j - 1 ;
52+ } else {
53+ if (i > 0 && charArray [i - 1 ] == '(' ) {
54+ numsStack .push (0 );
55+ }
56+ while (!opsStack .isEmpty () && opsStack .peek () != '(' ) {
57+ cal (numsStack , opsStack );
58+ }
59+ opsStack .push (c );
60+ }
61+ }
62+ while (!opsStack .isEmpty ()) {
63+ cal (numsStack , opsStack );
64+ }
65+ return numsStack .peek ();
66+ }
67+
68+ private void cal (Deque <Integer > numsStack , Deque <Character > opsStack ) {
69+ if (numsStack .isEmpty () || numsStack .size () < 2 || opsStack .isEmpty ()) {
70+ return ;
71+ }
72+ int b = numsStack .pop (), a = numsStack .pop ();
73+ char op = opsStack .pop ();
74+ numsStack .push (op == '+' ? a + b : a - b );
75+ }
76+ }
77+
78+
79+ /*
80+ ArrayDeque使用不同的api
81+ */
82+ class Solution {
83+ public int calculate (String s ) {
84+ Deque <Character > opsQueue = new ArrayDeque <>();
85+ Deque <Integer > numsQueue = new ArrayDeque <>();
86+ numsQueue .addLast (0 );
87+ s = s .replaceAll (" " , "" );
88+ int n = s .length ();
89+ char [] charArray = s .toCharArray ();
90+ for (int i = 0 ; i < n ; i ++) {
91+ char c = charArray [i ];
92+ if (c == '(' ) {
93+ opsQueue .addLast (c );
94+ } else if (c == ')' ) {
95+ while (!opsQueue .isEmpty () && opsQueue .peekLast () != '(' ) {
96+ cal (numsQueue , opsQueue );
97+ }
98+ opsQueue .pollLast ();
99+ } else if (Character .isDigit (c )) {
100+ int j = i , num = 0 ;
101+ while (j < n && Character .isDigit (charArray [j ])) {
102+ num = num * 10 + charArray [j ++] - '0' ;
103+ }
104+ numsQueue .addLast (num );
105+ i = j - 1 ;
106+ } else {
107+ if (i > 0 && charArray [i - 1 ] == '(' ) {
108+ numsQueue .addLast (0 );
109+ }
110+ while (!opsQueue .isEmpty () && opsQueue .peekLast () != '(' ) {
111+ cal (numsQueue , opsQueue );
112+ }
113+ opsQueue .addLast (c );
114+ }
115+ }
116+ while (!opsQueue .isEmpty ()) {
117+ cal (numsQueue , opsQueue );
118+ }
119+ return numsQueue .peekLast ();
120+ }
121+
122+ private void cal (Deque <Integer > numsQueue , Deque <Character > opsQueue ) {
123+ if (numsQueue .isEmpty () || numsQueue .size () < 2 || opsQueue .isEmpty ()) {
124+ return ;
125+ }
126+ int b = numsQueue .pollLast (), a = numsQueue .pollLast ();
127+ char op = opsQueue .pollLast ();
128+ numsQueue .addLast (op == '+' ? a + b : a - b );
129+ }
130+ }
0 commit comments