题解 | #表达式求值#
表达式求值
https://www.nowcoder.com/practice/c215ba61c8b1443b996351df929dc4d4
Leetcode上有一个类似的224. 基本计算器 但是题目中之要求了'+'和'-',是Hard,我之前做的时候,没有用栈,可以不考虑运算的优先级,直接计算,牛客的该提,是包含乘的,需要考虑运算优先级,所以用了个栈,具体求解看下面(官方题解代码写的是真的烂......)。
/** * 根据对应的算法表达式计算结果 * @param s * @return 返回表达式对应的值,表达式包含加减乘,但是感觉除也没啥区别 */ public int solve (String s) { // 特殊处理 if (s.isEmpty()){ return 0; } int res=0,flag=1; Stack<Integer> resArr=new Stack<>(); // 正负号处理:-(2*6)这种特殊情况 if (s.charAt(0)=='-'){ flag=-1; s=s.substring(1); } char op='+'; // 这里没有i++,是因为下面要动态更新i的值,逻辑更清晰。 for (int i=0;i<s.length();){ char tmp=s.charAt(i); // 更新最近遇到对运算符 if (tmp=='+'||tmp=='-'||tmp=='*'){ op=tmp; i++; // 碰到左括号 }else if (tmp=='('){ int j=i+1,num_bracket=1; // 将最外层左括号对应对有括号中的表达式当成一个整体进行递归处理 // 统计括号对数量是因为有可能有括号嵌套:(()) while (j<s.length()&&num_bracket>0){ if (s.charAt(j)=='(') { num_bracket++; }else if (s.charAt(j)==')'){ num_bracket--; } j++; } // s.substring()对原始字符串做切割 calculate(resArr,solve(s.substring(i+1,j-1)),op); i=j; // 碰到右括号因为上面左括号已经处理过了,直接continue }else if (tmp==')'){ i++; // 碰到数字字符 }else{ int j=i; // 将连续数字字符转成数字:"32233" // Character.isDigit()判断给定的char是否是个数字 while (j<s.length()&&Character.isDigit(s.charAt(j))){ j++; } // Integer.parseInt()函数将给定字符串专程int变量 calculate(resArr,Integer.parseInt(s.substring(i,j)),op); i=j; } } // 栈求和,采用Stream流求和代码更优雅 res= resArr.stream().mapToInt(Integer::intValue).sum(); return flag*res; } /** * 根据给定的操作符将对应数字压栈 * @param resArr {@link Stack<Integer>} 存储Integer类型的Stack * @param num int型变量 * @param op char型变量 */ public void calculate(Stack<Integer> resArr,int num,char op){ switch (op){ // '+' 直接将原始数字压栈 case '+': resArr.add(num); break; // '-' 将原始数字的相反数压栈 case '-': resArr.add(-num); break; // '*' 更新栈顶元素与原始数字相乘后压栈 case '*': resArr.push(resArr.pop()*num); } }