题目描述:
输入: 字符串格式的算术表达式,如: “3+2*{1+2*[-4/(8-6)+7]}”, 数字部分无小数
输出: 计算结果
思路: 使用两个栈, 一个保存运算符, 一个保存数字
这个题目主要是各类特殊情况需要考虑比较多
java代码实现:
import java.util.*;
@SuppressWarnings("unchecked")
public class Main{
public static void main(String[] args){
Scanner sc = new Scanner(System.in);
while(sc.hasNext()){
String str = sc.nextLine();
Stack sn = new Stack();
Stack so = new Stack();
so.push('(');
str = str +")";
for(int i = 0; i<str.length(); i++){
char ch = str.charAt(i);
/***数字部分开始***/
int tmpInt = 0;
boolean isDigit = false;
// 循环处理多位数
while(isDigit(ch)){
tmpInt = tmpInt*10 + (ch-'0');
i++;
ch = str.charAt(i);
isDigit = true;
}
if(isDigit){
i--; //多位数字最后一次i++回退
sn.push(tmpInt);
continue;
}
/***数字部分开始***/
/***运算符部分开始***/
// 如果是(则直接压入so
if(isEqualLeft(ch)){
so.push('(');
continue;
}
// 处理负号, 转换为0-x的样式, 负号前面不能为数字或者右括号; 考虑特殊情况, 第一个数字是负数(牛客网上面这一题测试用例没考虑到这个情况)
if(ch == '-' && (((i-1)>=0 && !isDigit(str.charAt(i-1)) && !isEqualRight(str.charAt(i-1))) || i==0)){
sn.push(0);
}
char ch1 = (char)so.peek();
// 大于前一个运算符优先级 或者 前面的数字少于2个(无法凑出一次运算), 则直接推入运算符
if(isPriority(ch1, ch) || sn.size()<2){
so.push(ch);
}else{
if(isEqualRight(ch)){
handleCal(sn, so, ch);
if(!so.isEmpty() && isEqualLeft((char)so.peek())){
so.pop();
}
}else{
handleCal(sn, so, ch);
so.push(ch);
}
}
/***运算符部分结束***/
}
System.out.println(sn.pop());
}
}
private static boolean isEqualLeft(char ch){
if(ch == '(' || ch == '{' || ch == '['){
return true;
}
return false;
}
private static boolean isEqualRight(char ch){
if(ch == ')' || ch == '}' || ch == ']'){
return true;
}
return false;
}
private static void handleCal(Stack sn, Stack so, char ch){
while(!so.isEmpty() && !isEqualLeft((char)so.peek()) && !isPriority((char)so.peek(),ch)){
int valb = (int)sn.pop();
int vala = (int)sn.pop();
char op = (char)so.pop();
int res = calculateVal(vala, valb, op);
sn.push(res);
}
}
private static int calculateVal(int vala, int valb, char op){
if(op == '+'){
return vala + valb;
}
if(op == '-'){
return vala - valb;
}
if(op == '*'){
return vala * valb;
}
if(op == '/'){
return vala / valb;
}
return 0;
}
private static boolean isDigit(char ch){
if(ch<='9' && ch>='0'){
return true;
}
return false;
}
private static boolean isPriority(char ch1, char ch2){
if(ch2 == ')'){
return false;
}
if((ch2 == '*' || ch2 == '/') && (ch1 == '+' || ch1 == '-')){
return true;
}
return false;
}
}