原题
题解
方法一 转化为若干数字的和
总说:
在多则运算中,乘法和除法的优先级比加减法要高,因此在运算的时候,我们要先把数字两边有乘除号的那些数字看做整体优先运算出结果,然后再把所有代表结果的数字的数字相加就是最终的结果。
思路步骤:
1、 首先建立一个ArrayList list来存储所有待加的数字(当然如果某个数字或者某个乘除字符段之前是减号,那我们在存入数字的实后可以去相反数,这一点在下面步骤4会提到的);
2、 利用一个变量i作为指针,从头到尾来遍历s的所有字符,当然在开始遍历之前,要把s处理成前后都没有空格的字符串,这样可以减少麻烦;利用变量shuzi(每一次处理完后,shuzi会被初始化为0)来记录运算符之间的数字,利用变量fuhao来记录之前最后出现的运算符(对应关系为:0+、1-、2*、3/),以便知道在将数字放入list或者修改list中的数字之时的具体操作;
3、 先说一下,当i指向的位置是数字的时候,我们需要先把这一位字符和转换成整型数,当然这一位数字可能不是单独的一位数,那么我们就需要根据十进制来进行处理(比如32,i指向3的时候,首先shuzi被赋予了3,当下一轮循环,i指向2的时候,我们需要把shuzi的值乘10在加上2);而如果我们在某时已经遍历到s的最后一位了,就需要也把此时得到的shuzi,进行步骤4里面的处理;
4、 现在说i指向的位置时运算符号。我们遇到运算符号的时候,首先要考虑在这个运算符号之前的遇到的上一个运算符号是什么,因为这关系到了我们此时如何处理现在得到的变量shuzi。上一个运算符符号是什么,我利用了变量fuhao以0-3的数字来表示:
- 当fuhao==0的时候,也就是加号+,意味着当前的shuzi在式子中作为加数,因此直接加入list;
- 当fuhao==1的时候,也就是减号-,意味着当前的shuzi在式子中作为减数数,因此取反后加入list;
- 当fuhao==2的时候,也就是乘号*,意味着当前的shuzi是和已加入list的最后一个数作了乘法运算,需要修改list里面最后的数字的值,乘上shuzi
- 当fuhao==3的时候,也就是除号*,意味着当前的shuzi是和已加入list的最后一个数作了除法运算,需要修改list里面最后的数字的值,除以shuzi
当然每一次经过步骤4之后,都需要初始化shuzi为0,以便于后边继续利用它处理后边的内容。
5、 最后一步,把list里面的所有数加起来得到最后结果,就想做简单的加法题一样。
本思路java代码示例:
/*
@v7fgg
执行用时:22 ms, 在所有 Java 提交中击败了41.89%的用户
内存消耗:40.3 MB, 在所有 Java 提交中击败了100.00%的用户
2020年7月15日 14:55
*/
class Solution {
public int calculate(String s) {
s=s.trim();
List<Integer> list=new ArrayList<>();
int i=0;//指针
int shuzi=0;//记录每两个运算符之间的数字
int fuhao=0;//记录上一个运算符是什么:0+、1-、2*、3/
while(i<s.length()){
//对于空格就跳过直到不是为止
while(s.charAt(i)==' '){
i++;
}
//对于数字,要用逐位乘10相加的方法算出具体值
if(s.charAt(i)>='0'&&s.charAt(i)<='9'){
shuzi=10*shuzi+s.charAt(i)-'0';
//特殊情况假如已经到达字符串末端,则要把最后一个数的运算结果归档
if(i==s.length()-1){
if(fuhao==0){list.add(shuzi);}
else if(fuhao==1){list.add(-shuzi);}
else if(fuhao==2){
list.set(list.size()-1,shuzi*list.get(list.size()-1));
}
else{
list.set(list.size()-1,list.get(list.size()-1)/shuzi);
}
}
}
//而对于运算符号,需要先把前面得到数字归档
else{
if(fuhao==0){list.add(shuzi);}
else if(fuhao==1){list.add(-shuzi);}
//乘除比较特殊,要把list里面最后的数字进行修改
else if(fuhao==2){
list.set(list.size()-1,shuzi*list.get(list.size()-1));
}
else{
list.set(list.size()-1,list.get(list.size()-1)/shuzi);
}
shuzi=0;//变量shuzi要初始化
if(s.charAt(i)=='+'){fuhao=0;}
else if(s.charAt(i)=='-'){fuhao=1;}
else if(s.charAt(i)=='*'){fuhao=2;}
else{fuhao=3;}
}
i++;
}
int ans=0;
for(int j=0;j<list.size();j++){
ans+=list.get(j);
}
return ans;
}
}
当然我们也可以不用ArrayList,改用Stack,解题的原理还是一样的。
利用Stack代码示例:
/*
@v7fgg
执行用时:18 ms, 在所有 Java 提交中击败了52.12%的用户
内存消耗:40.8 MB, 在所有 Java 提交中击败了100.00%的用户
2020年7月15日 15:13
*/
class Solution {
public int calculate(String s) {
s=s.trim();
Stack<Integer> stack=new Stack<>();
int i=0;//指针
int shuzi=0;//记录每两个运算符之间的数字
int fuhao=0;//记录上一个运算符是什么:0+、1-、2*、4/
while(i<s.length()){
//对于空格就跳过直到不是为止
while(s.charAt(i)==' '){
i++;
}
//对于数字,要用逐位乘10相加的方法算出具体值
if(s.charAt(i)>='0'&&s.charAt(i)<='9'){
shuzi=10*shuzi+s.charAt(i)-'0';
//特殊情况假如已经到达字符串末端,则要把最后一个数的运算结果归档
if(i==s.length()-1){
if(fuhao==0){stack.push(shuzi);}
else if(fuhao==1){stack.push(-shuzi);}
else if(fuhao==2){
stack.push(shuzi*stack.pop());
}
else{
stack.push(stack.pop()/shuzi);
}
}
}
//而对于运算符号,需要先把前面得到数字归档
else{
if(fuhao==0){stack.push(shuzi);}
else if(fuhao==1){stack.push(-shuzi);}
else if(fuhao==2){
stack.push(shuzi*stack.pop());
}
else{
stack.push(stack.pop()/shuzi);
}
shuzi=0;//变量shuzi要初始化
if(s.charAt(i)=='+'){fuhao=0;}
else if(s.charAt(i)=='-'){fuhao=1;}
else if(s.charAt(i)=='*'){fuhao=2;}
else{fuhao=3;}
}
i++;
}
int ans=0;
while(!stack.empty()){
ans+=stack.pop();
}
return ans;
}
}