题目:
Implement a basic calculator to evaluate a simple expression string.
The expression string contains only non-negative integers, +
, -
, *
, /
operators and empty spaces . The integer division should truncate toward zero.
You may assume that the given expression is always valid.
Some examples:
"3+2*2" = 7 " 3/2 " = 1 " 3+5 / 2 " = 5
Note: Do not use the eval
built-in library function.
题意:简易计算器,可以进行四则运算
思路:在I的基础上可以很清晰的分析此题,利用两个Stack,一个存储数字,一个存储符号需要注意一下几点:
(1)连续的数字需要进行处理;
(2)乘除需要在后一个数字入栈后处理;
(3)最后栈内剩余为加减法,只需要一步步弹出即可,需要记住一次只弹出一个数字和符号,不能两个数字运算,在I中有说明,遗忘的话可以点击-> Basic Calculator I
(4)需要对最后一个数字进行特殊处理,因为前面的方法只有检测到有符号的时候才会将数字如栈。
代码(后面有优化版):
public class Solution { public int calculate(String s) { if(s == null || s.length() == 0) return 0; Stack<Integer> num = new Stack<Integer>(); Stack<Character> symbol = new Stack<Character>(); boolean isNum = false; int count = 0; for(int i = 0 ; i < s.length() ; i++){ if(s.charAt(i) == ' ') continue; char temp = s.charAt(i); if(Character.isDigit(temp)){ count = count * 10 + (temp - '0') ; isNum = true; }else if(isNum){ num.push(count); count = 0; isNum = false; if(!symbol.isEmpty() && (symbol.peek() == '*' || symbol.peek() == '/')){ char tempSymbol = symbol.pop(); int b = num.pop(); int a = num.pop(); if(tempSymbol == '*'){ num.push(a*b); }else{ num.push(a/b); } } } if(!Character.isDigit(temp)){ symbol.push(temp); } } if(isNum){ num.push(count); if(!symbol.isEmpty() && (symbol.peek() == '*' || symbol.peek() == '/')){ char tempSymbol = symbol.pop(); int b = num.pop(); int a = num.pop(); if(tempSymbol == '*'){ num.push(a*b); }else{ num.push(a/b); } } } if(!symbol.isEmpty()){ int rep = 0; while(!symbol.isEmpty()){ char tempSymbol = symbol.pop(); int a = num.pop(); if(tempSymbol == '+'){ rep+=a; }else{ rep-=a; } } num.push(rep + num.pop()); } return num.pop(); } }
优化思路:注意到代码有冗余的部分,是因为每一次数字入栈是在判断有符号的时候,这时,可以人为的在初始出入的String的末尾加入非运算符号,这样可以将二者整合到一起。
优化后代码:
public class Solution { public int calculate(String s) { if(s == null || s.length() == 0) return 0; Stack<Integer> num = new Stack<Integer>(); Stack<Character> symbol = new Stack<Character>(); s += "#"; boolean isNum = false; int count = 0; for(int i = 0 ; i < s.length() ; i++){ if(s.charAt(i) == ' ') continue; char temp = s.charAt(i); if(Character.isDigit(temp)){ count = count * 10 + (temp - '0') ; // 连续的数字 isNum = true; }else{ if(isNum){ // 遇到符号 将前面数字压入 num.push(count); count = 0; isNum = false; if(!symbol.isEmpty() && (symbol.peek() == '*' || symbol.peek() == '/')){ char tempSymbol = symbol.pop(); int b = num.pop(); int a = num.pop(); if(tempSymbol == '*'){ num.push(a*b); }else{ num.push(a/b); } } } if(temp != '#'){ // 将符号压入 symbol.push(temp); } } } if(!symbol.isEmpty()){ int rep = 0; while(!symbol.isEmpty()){ // 加减运算 char tempSymbol = symbol.pop(); int a = num.pop(); if(tempSymbol == '+'){ rep+=a; }else{ rep-=a; } } num.push(rep + num.pop()); } return num.pop(); } }