题目描述
实现一个基本的计算器来计算一个简单的字符串表达式的值。
字符串表达式仅包含非负整数,+, - ,*,/ 四种运算符和空格 。 整数除法仅保留整数部分。
示例 1:
输入: “3+2*2”
输出: 7
示例 2:
输入: " 3/2 "
输出: 1
示例 3:
输入: " 3+5 / 2 "
输出: 5
思路分析
1.将中缀表达式转为后缀表达式
2.计算后缀表达式
中缀表达式转后缀表达式方法:
- 设置一个栈
operators
存储运算符 - 逐个读取字符串的内容,如果是数字,直接输出到后缀表达式中;如果是运算符:先比较栈顶运算符和当前读取的运算符优先级,如果栈为空,直接将运算符入栈;如果栈顶运算符优先级 >= 当前运算符优先级,则将当前栈顶元素输出到后缀表达式中,重复该操作,直至栈空或栈顶运算符优先级 < 当前运算符优先级。
注意:操作数不一定只占一个字符
后缀表达式计算方法:
- 设置一个栈
operands
存储操作数,依次读取后缀表达式的内容 - 如果是操作数,则将它放入栈中;如果是操作符,从栈中提取两个操作数,按照先后记为
num2
,num1
(先取的是num2
)然后进行运算num1 optr num2
,将结果压回栈中。
代码
class Solution {
public static int calculate(String s) {
Stack<Integer> operands = new Stack<>();
List<String> postfix = infixToPostfix(s);
for(String e: postfix){
if(Character.isDigit(e.charAt(0)))
operands.push(Integer.parseInt(e));
else{
int num2 = operands.pop(), num1 = operands.pop();
int res = calculate(num1, num2, e);
operands.push(res);
}
}
return operands.pop();
}
private static int calculate(int num1, int num2, String operator){
int res = 0;
switch (operator){
case "+": res = num1 + num2;break;
case "-": res = num1 - num2;break;
case "*": res = num1 * num2;break;
case "/": res = num1 / num2;break;
}
return res;
}
private static List<String> infixToPostfix(String s){
Stack<Character> operators = new Stack<>();
List<String> postfix = new ArrayList<>();
for(int i=0;i<s.length();i++){
char c = s.charAt(i);
if(c == ' ')
continue;
if(Character.isDigit(c)){
String num = getNum(s, i);
postfix.add(num);
while(i + 1 < s.length() && Character.isDigit(s.charAt(i + 1)))
i++;
}
else{
while(!operators.isEmpty() && comparePriority(c, operators.peek()) <= 0) //栈顶运算符优先级大于等于当前运算符
postfix.add(operators.pop() + "");
operators.push(c);
}
}
while(!operators.isEmpty())
postfix.add(operators.pop() + "");
return postfix;
}
private static String getNum(String s, int startOfNum){
int endOfNum = startOfNum + 1;
while(endOfNum < s.length()){
char c = s.charAt(endOfNum);
if(!Character.isDigit(c))
break;
endOfNum++;
}
String num = s.substring(startOfNum, endOfNum);
return num;
}
private static int comparePriority(char optr1, char optr2){
if(optr1 == '*' || optr1 =='/'){
if(optr2 == '*' || optr2 =='/')
return 0;
else return 1;
}else{
if(optr2 == '*' || optr2 =='/')
return -1;
else return 0;
}
}
}