227. Basic Calculator II
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.
题目分析:
输入一个运算的字符串,需要输出字符串的运行结果。题目假定输入的运算字符串都是有意义的。
思路简介:
思路一:只从字符串处理的角度出发的话,我考虑使用Stack来处理这题。
首先,将字符串从后向前存入栈中,这样栈弹出的时候就与字符串的真实顺序一致。每次存要么存数,要么存操作符,这样之后弹出的元素就是一个完整的部分。
初始化sum=0;每次Stack弹出三个元素,其中一定包含两个数字和一个操作符号(num1,oper,num2)。
如果符号是"+"那么将第一个数字加到sum中,将num2压回栈中(因为不知道num2之后的操作符是否比oper优先级高)
如果符号是"-"那么将num2取负,并压回栈中。
如果符号是" * “ ” / ",将num1和num2的运算结果压回栈中。
之后代码我实现了两个方式,一个是将操作符和数字都存在一个Stack<String>中。二是分开存储NumStack<Integer>/OperStack<Character>,但是二者的速度差不多,失败~~
复杂度:
时间复杂度O(N)
空间复杂度O(N)
代码:
public class Solution {
public int calculate(String s) {
//方法一,用一个栈来做这件事
/*
Stack<String> aStack = new Stack<String>();
getStack(aStack,s);
int sum=0;
while(true){
String num1=aStack.pop();
if(aStack.isEmpty()==true){
sum += Integer.parseInt(num1);
break;
}
String oper=aStack.pop();
String num2=aStack.pop();
if(oper.charAt(0)=='+'||oper.charAt(0)=='-'){
sum +=Integer.parseInt(num1);
if(oper.charAt(0)=='-'){
num2 = "-"+num2;
}
aStack.push(num2);
}else{
if(oper.charAt(0)=='*'){
aStack.push(Integer.parseInt(num1)*Integer.parseInt(num2)+"");
}else{
aStack.push(Integer.parseInt(num1)/Integer.parseInt(num2)+"");
}
}
}
return sum;
*/
//方法二:分开处理这件事
Stack<Integer> aNumStack= new Stack<Integer>();
Stack<Character> aOperStack= new Stack<Character>();
int sum = 0;
getStack(aOperStack,aNumStack,s);
if(aOperStack.isEmpty()==true){
return aNumStack.pop();
//break;
}
while(true){
int num1 = aNumStack.pop();
int num2 = aNumStack.pop();
char oper = aOperStack.pop();
if(oper=='+'||oper=='-'){
sum += num1;
if(oper == '-'){
num2 = -1*num2;
}
aNumStack.push(num2);
}else{
if(oper == '*'){
aNumStack.push(num1*num2);
}else{
aNumStack.push(num1/num2);
}
}
if(aOperStack.isEmpty()==true){
sum+= aNumStack.pop();
break;
}
}
return sum;
}
//用一个栈来解决所有问题,简单但是速度慢
public void getStack(Stack<String> aStack,String s){
String aSec="";
for(int i=s.length()-1;i>=0;i--){
//String aSec="";
if(s.charAt(i)!=' '){
if(s.charAt(i)<='9'&&s.charAt(i)>='0'){
aSec = s.charAt(i)+aSec;
}else{
aStack.push(aSec);
aStack.push(s.charAt(i)+"");
aSec="";
}
}
}
aStack.push(aSec);
}
//一个栈存储数字,一个栈存储操作符
public void getStack(Stack<Character> aOperStack,Stack<Integer> aNumStack,String s){
String aSec="";
for(int i=s.length()-1;i>=0;i--){
if(s.charAt(i)!=' '){
if(s.charAt(i)<='9' && s.charAt(i)>= '0'){
aSec = s.charAt(i)+aSec;
}else{
aNumStack.push(Integer.parseInt(aSec));
aOperStack.push(s.charAt(i));
aSec="";
}
}
}
aNumStack.push(Integer.parseInt(aSec));
}
}
运行结果:
(依旧不能贴图,我上个数字)8.78%
ps:这个方法是比较暴力的方法,之后好的方法再陆续补充
———————————————————————————————————————————————————————————
【转载自】微信公众号:每日一道算法题
求一个简单的数学运算表达式的值,运算符总是在两个运算对象之间。一般用数学表达式的是 中缀表达式 如1+5*2。中缀表达式的特点:1.对人比较友好,但是对机器并不友好,不利于计算(编译器一般会将中缀表达式翻译成逆波兰表达式 )2,不能表示计算的顺序,需要借助括号等符号;3。操作符在操作数的中间。
逆波兰表达式又叫后缀表达式,据说是波兰人发明的。后缀表达式的特点是操作符都在操作数的后面,并且特别方便计算。因为它的顺序可以表示计算的顺序,不需要借助括号。
改进1:
不需要将String 存储到 Stack中,直接从前向后遍历String,可以将空间复杂度缩小为 O(1)