## 题目:
给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。
- `1 <= s.length <= 3 * 105`
- `s` 由整数和算符 `('+', '-', '*', '/')` 组成,中间由一些空格隔开
整数除法仅保留整数部分。
你可以假设给定的表达式总是有效的。所有中间结果将在 [-231, 231 - 1] 的范围内。
注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。
### 示例:
#### 示例 1:
输入:s = "3+2*2"
输出:7
#### 示例2:
输入:s = " 3/2 "
输出:1
#### 示例3:
输入:s = " 3+5 / 2 "
输出:5
---
【方法一】双栈
![[Pasted image 20220901183359.png]]
```
class Solution {
//思路:用两个栈,一个数字栈,一个符号栈;以及一个哈希表来存储运算符号的优先级
static Stack<Integer> num = new Stack<Integer>();
static Stack<Character> op = new Stack<Character>();
static HashMap<Character, Integer> map = new HashMap<Character, Integer>();
//定义一个eval()函数:用于从数字栈num中弹出两个数字a和b,再从操作符栈op中弹出操作符号,进行计算后将结果数字加入到数字栈num中。
static void eval(){
int a = num.pop();
int b = num.pop();
int c = op.pop();
int res = 0; //a和b经c运算后结果
if(c == '+') res = a + b;
else if(c == '-') res = b - a;
else if(c == '*') res = a * b;
else res = b / a;
num.push(res); //将结果入栈num
}
public int calculate(String s) {
s = '0' + s; //对给的字符串表达式开头是负数的处理
map.put('+', 1); //设计一个哈希表来存储'+','-','*','/' 优先级,我们将'+'和'-'设为1级优先级,将'*'和'/'设为2级优先级。
map.put('-', 1);
map.put('*', 2);
map.put('/', 2);
for(int i = 0; i < s.length(); i++){
char c = s.charAt(i);
if(c == ' ') continue; //跳过空格
if(c >= '0' && c <= '9'){ //当c是数字,读取一个连续的数字
int x = 0
while(i < s.length() && s.charAt(i) >= '0' && s.charAt(i) <= '9'){
x = x * 10 + s.charAt(i++) - '0';
}
i--;
num.push(x);
}else{ //当c是操作符
//当op栈非空且栈顶操作符优先级大于等于当前操作符c的优先级,进行eval()操作
while(!op.isEmpty() && map.get(op.peek()) >= map.get(c)){
eval();
}
op.push(c);
}
}
while(!op.isEmpty()) eval();
return num.pop();
}
}
```
【方法二】单栈
说明:**所有运算最后都是一个个数做加法。**
遇到减号,就让这个数变负
遇到乘号,就让当前的数乘上之前的数
遇到除号,就让当前数被之前的数除
所以需要一个栈,去存这些最后会做加法的计算结果;还要一个变量,记录上一个运算符是什么,它决定了怎么处理当前的数
```
class Solution {
public int calculate(String s) {
//Deque<Integer> stack = new ArrayDeque<Integer>(); //用Deque比Stack耗时少
Stack<Integer> stack = new Stack<Integer>();
char preSign = '+'; //此变量记录上一个运算符是什么
int num = 0;
int n = s.length();
for (int i = 0; i < n; ++i) {
if (Character.isDigit(s.charAt(i))) {
num = num * 10 + s.charAt(i) - '0';
}
if (!Character.isDigit(s.charAt(i)) && s.charAt(i) != ' ' || i == n - 1) {
switch (preSign) {
case '+':
stack.push(num);
break;
case '-':
stack.push(-num);
break;
case '*':
stack.push(stack.pop() * num);
break;
default:
stack.push(stack.pop() / num);
}
preSign = s.charAt(i);
num = 0;
}
}
int ans = 0;
while (!stack.isEmpty()) {
ans += stack.pop();
}
return ans;
}
}
```
【方法三】逆波兰式???