leetcode 277 基本计算器 Basic Calculator II (单栈,单次遍历,思路简单)
程序员文章站
2022-07-15 12:24:04
...
因只有两个优先级:+ - or * / 所以相对比较简单
只要你点开了这篇,就一定可以学会了出去!!
思路:遍历一次字符串
1.遇到空格跳过
2.若碰到数字则取得该数字全部字符入栈
3.若碰到加减则把入栈数字*原符号追加进结果,更新符号
4.若碰到乘除则把入栈数字与符号后的数字运算后重新入栈
1.定义全局变量
这里我们需要三个全局变量,stack[]作为数字栈存放还未计算完成的数,
sign存放已经遍历到但还未参与计算的+ or -,定义为 1 or -1(为什么定义为这两个值,为了方便相乘鸭!!),初始为+,
answer存放计算结果。
2.遍历
Number
当遇到0-9的数字时,万不可直接push进栈,因为有可能是几十,几百或者几千。首先要做的是找全这个数字。
if (s[i]>=0 && s[i]<=9) { //maybe 24, 109 and so on
let k =i+1;
while(s[k]>=0 && s[k]<=9 ) k++; //找到此数字最后一个index,此时k为此index+1
if(k!==(i+1)){ //两位数以上
stack.push(s.substring(i,k));
i = k-1; //因为for循环中还有一次i++
}else { //一位数
stack.push(s[i]);
}
}
加减
加减其实计算的是前一个加减符号到这一个之间的值,所以是用之前存放的sign*这一段的计算结果(stack.pop())
if (s[i] == '+' || s[i] == '-'){
if(stack.length) answer += stack.pop() * sign; // 这里加if判断是避免第一个数字是负数的情况
sign = (s[i] == '+' ? 1 : -1); //更新sign
}
乘除
乘除计算的是当前这个符号前后两个数字,计算结果入栈。(符号前数字在栈中,符号后数字需要用上述Number方法找全数字)
if (s[i] == '*' || s[i] == '/') {
//找符号后全数字
let j = i+1;
while (s[j]==' ') j++; //有空格则startIndex后移
let k = j+1;
while(s[k]>=0 && s[k]<=9 ) k++;
let newWord = null;
if(k == (j+1)) newWord = s[j];
else newWord = s.substring(j,k);
//计算
if(s[i] == '*') stack.push( stack.pop() * Number(newWord));
else stack.push(Math.floor(stack.pop() / Number(newWord)));
i = k-1;
}
如此,便完成了所有逻辑块。
全部代码
var calculate = function(s) {
let sign = 1 ; //1 equal + ; -1 equal -
let stack = []; //存放数字
let answer = 0;
for(let i = 0 ; i <s.length ; i++){
if(s[i] == ' ') continue; // space pass
else if (s[i]>=0 && s[i]<=9) { //maybe 24, 109 and so on
let k =i+1;
while(s[k]>=0 && s[k]<=9 ) k++; //找到此数字最后一个index,此时k为此index+1
if(k!==(i+1)){ //两位数以上
stack.push(s.substring(i,k));
i = k-1; //因为for循环中还有一次i++
}else { //一位数
stack.push(s[i]);
}
}
else if (s[i] == '+' || s[i] == '-'){
if(stack.length) answer += stack.pop() * sign; // 这里加if判断是避免第一个数字是负数的情况
sign = (s[i] == '+' ? 1 : -1); //更新sign
}else if (s[i] == '*' || s[i] == '/') {
//找符号后全数字
let j = i+1;
while (s[j]==' ') j++; //有空格则startIndex后移
let k = j+1;
while(s[k]>=0 && s[k]<=9 ) k++;
let newWord = null;
if(k == (j+1)) newWord = s[j];
else newWord = s.substring(j,k);
//计算
if(s[i] == '*') stack.push( stack.pop() * Number(newWord));
else stack.push(Math.floor(stack.pop() / Number(newWord)));
i = k-1;
}
}
//计算最后一个剩余数字
while(stack.length){
answer += Number(stack.pop()) * sign; //leave the last number
}
return answer;
};
如有任何不解,欢迎随时交流
上一篇: BZOJ1479 最大获利
下一篇: 到达终点数字