实现一个基本的计算器来计算一个简单的字符串表达式的值
字符串表达式可以包含左括号 ( ,右括号 ),加号 + ,减号 -,非负整数和空格 。
示例 1:
输入: “1 + 1”
输出: 2
示例 2:
输入: " 2-1 + 2 "
输出: 3
示例 3:
输入: “(1+(4+5+2)-3)+(6+8)”
输出: 23
说明:
你可以假设所给定的表达式都是有效的。
请不要使用内置的库函数 eval。
双栈
1.使用两个栈,stack0 用于存储操作数,stack1 用于存储操作符
2.从左往右扫描,遇到操作数入栈 stack0
3.遇到操作符时,如果当前优先级低于或等于栈顶操作符优先级,则从 stack0 弹出两个元素,从 stack1 弹出一个操作符,进行计算,将结果并压入stack0,继续与栈顶操作符的比较优先级。
4.如果遇到操作符高于栈顶操作符优先级,则直接入栈 stack1
5.遇到左括号,直接入栈 stack1。
6.遇到右括号,则从 stack0 弹出两个元素,从 stack1 弹出一个操作符进行计算,并将结果加入到 stack0 中,重复这步直到遇到左括号
因为我们只有加法和减法,所以这个流程可以简化一下。
第 3 条改成「遇到操作符时,则从 stack0 弹出两个元素进行计算,并压入stack0,直到栈空或者遇到左括号,最后将当前操作符压入 stack1 」
第 4 条去掉,已经和第 3 条合并了。
解题思路:
判断是否为数字 是数字计算其值
不是数字,则先数字加入栈中
运算符分为括号和其它
括号 左括号入栈,右括号 直到左括号出现 否则就运算
其它运算符 一直出栈直到栈空或者出现左括号 运算
public class Leetcode224 {
public int calculate(String s) {
char[] array = s.toCharArray();
int length = array.length;
// 双栈
Stack<Integer> num = new Stack<>();
Stack<Character> op = new Stack<>();
int temp = -1;
for(int i=0;i<length;i++) {
if(array[i]==' ') {
continue;
}
// 数字进行累加
if(isNumber(array[i])) {
if(temp==-1) {
temp = array[i] - '0';
}else {
temp = temp*10+array[i]-'0';
}
}else {
// 将数字入栈
if(temp!=-1) {
num.push(temp);
temp=-1;
}
// 操作符+ -
if(isOperation(array[i] + "")) {
while(!op.isEmpty()) {
if(op.peek()=='(') {
break;
}
// 不停的出栈,进行运算,并将结果再次压入栈中
int num1 = num.pop();
int num2 = num.pop();
if(op.pop()=='+') {
num.push(num2+num1);
}else {
num.push(num2-num1);
}
}
// 当前运算符入栈
op.push(array[i]);
}else {
// 遇到括号
// 遇到左括号,直接入栈
if(array[i] =='(') {
op.push(array[i]);
}
// 遇到右括号,不停的运算,直到遇到左括号
if(array[i] == ')') {
while(op.peek()!='(') {
int num1 = num.pop();
int num2 = num.pop();
if(op.pop()=='+') {
num.push(num2+num1);
}else {
num.push(num2-num1);
}
}
op.pop();
}
}
}
}
if(temp!=-1) {
num.push(temp);
}
// 将栈中的其他元素继续运算
while(!op.isEmpty()) {
int num1 = num.pop();
int num2 = num.pop();
if(op.pop()=='+') {
num.push(num1+num2);
}else {
num.push(num2-num1);
}
}
return num.pop();
}
// 判断是否为数字
private static boolean isNumber(char c) {
return c>='0'&&c<='9';
}
// 判断是否为运算符
private static boolean isOperation(String t) {
return t.equals("+") || t.equals("-") || t.equals("*") || t.equals("/");
}
}