一、题目描述
给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。
整数除法仅保留整数部分。
你可以假设给定的表达式总是有效的。所有中间结果将在 [-231, 231 - 1] 的范围内。
注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。
示例 1:
输入:s = "3+2*2"
输出:7
示例 2:
输入:s = " 3/2 "
输出:1
示例 3:
输入:s = " 3+5 / 2 "
输出:5
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/basic-calculator-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、解题思路
1)首先需要将输入的字符串格式的表达式分解成每一项操作数或者操作符(运算符),用分解之后的的每一项构建后缀表达式,这里需要用到栈来辅助;
具体执行的思路可以参考:中缀表达式转换为后缀表达式-C++实现_中缀转后缀代码c++_TLJava^v^的博客-CSDN博客
2)根据后缀表达式进行求值,也是需要使用栈来辅助,具体执行思路可以参考:
后缀表达式求值-C++实现_c++后缀表达式求值_TLJava^v^的博客-CSDN博客
三、AC代码
class Solution {
private Map<String, Integer> opMap;
public int calculate(String s) {
// 先将字符串转化为后缀表达式,然后再对后缀表达式求值
initMap();
List<String> postExp = expToPost(s);
int ans = postCalculate(postExp);
return ans;
}
// 每个操作符的优先级,数值越大,优先级越高
private void initMap(){
opMap = new HashMap<>();
opMap.put("+", 1);
opMap.put("-", 1);
opMap.put("*", 2);
opMap.put("/", 2);
}
// 将表达式转换为后缀表达式
public List<String> expToPost(String s){
List<String> postExp = new ArrayList<>(); //存储后缀表达式
Deque<String> opStack = new LinkedList<>(); //操作符栈
int l = 0, r = 0, len = s.length(); //l, r分别指向子串的左右位置
// 转换过程
while(r < len){
while(r < len && s.charAt(r) == ' ') r++;
l = r;
if(l >= len) break;
if(Character.isDigit(s.charAt(l))){ //当前位置指向的是数字
while(r < len && Character.isDigit(s.charAt(r)))
r++;
postExp.add(s.substring(l, r)); //加入到后缀表达式中
}
else { //当前位置的是操作符
r++;
String op = s.substring(l, r);
// 优先级相等或更高的操作符加入到后缀表达式中
while(!opStack.isEmpty() && opMap.get(opStack.peek()) >= opMap.get(op)){
postExp.add(opStack.pop());
}
opStack.push(op);
}
}
while(!opStack.isEmpty()){ // 将剩下的操作符加入到后缀表达式的末尾
postExp.add(opStack.pop());
}
return postExp;
}
// 根据后缀表达式(用列表表示)求值,列表的每一项要么是操作数,要么是操作符
public int postCalculate(List<String> postExp){
Deque<Integer> numStack = new LinkedList<>();
for(String str : postExp){
if(!opMap.containsKey(str)){ //该项是操作数
numStack.push(Integer.valueOf(str));
}
else{
int num2 = numStack.pop(); //第二个操作数
int num1 = numStack.pop(); //第一个操作数
int res = 0;
if(str.equals("+")){
res = num1 + num2;
} else if(str.equals("-")){
res = num1 - num2;
} else if(str.equals("*")){
res = num1 * num2;
} else {
res = num1 / num2;
}
numStack.push(res);
}
}
//栈顶元素就是表达式的计算结果
return numStack.peek();
}
}