大家好我是苏麟 , 今天带来栈的比较难的问题 .
计算器问题
基础计算器 LeetCode 224
描述 :
给你一个字符串表达式 s
,请你实现一个基本计算器来计算并返回它的值。
s
由数字、'+'
、'-'
、'('
、')'
、和' '
组成s
表示一个有效的表达式- '+' 不能用作一元运算(例如, "+1" 和
"+(2 + 3)"
无效) - '-' 可以用作一元运算(即 "-1" 和
"-(2 + 3)"
是有效的) - 输入中不存在两个连续的操作符
- 每个数字和运行的计算将适合于一个有符号的 32位 整数
注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval()
。
题目 :
LeetCode 224.基本计算器 :
224. 基本计算器
分析 :
计算器也是非常常见的问题,解决运算器问题,最好的工具就是栈。我们需要两个变量来记录符号和运算后的值 , 因为题目中只有 + - ( ) 和空格 , 所以我们遇到空格就跳过 , 遇到就把符号位变为1 , 遇到减号就把符号位变为 -1 , 遇到 ( 就把计算的值和符号放到栈里 , 遇到 ) 就把栈中的值和符号取出来和当前的数字相加 , 遇到数字就进行操作 ... ...
当然这里说可能不太好理解 , 下面有个视频大家可以更好的理解这个思路 .
视频连接 : 基础计算器
解析 :
这个代码写的不是很华丽 , 但是是这个意思 ...
//LeetCode
class Solution {
public int calculate(String s) {
//0 + (1+(4+5+2)-3)+(6+8)
Stack<Integer> stack = new Stack<>();
int nums = 0;
int flag = 1;
int temp = 0;
int n = 0;
while( n < s.length()){
char c = s.charAt(n);
int d = c - '0';
if(c == ' '){
n++;
}else if(c == '+'){
flag = 1;
n++;
}else if(c == '-'){
flag = -1;
n++;
}else if(c == '('){
stack.push(nums);
stack.push(flag);
nums = 0;
flag = 1;
n++;
}else if(c == ')'){
int preFlag = stack.pop();
int preNums = stack.pop();
nums = nums * preFlag + preNums;
n++;
}else{
temp = c - '0';
n++;
while(n < s.length() && s.charAt(n) >= '0' && s.charAt(n) <= '9'){
char r = s.charAt(n);
temp = 10 * temp + (r - '0');
n++;
}
nums = nums + temp * flag;
}
}
return nums;
}
}
基础计算器 LeetCode 227
描述 :
给你一个字符串表达式 s
,请你实现一个基本计算器来计算并返回它的值。
整数除法仅保留整数部分。
题目 :
LeetCode 227.基础计算器
227. 基本计算器 II
分析 :
解决运算器问题,最好的工具就是栈。由于乘除优先于加减计算,因此不妨考虑先进行所有乘除运算,并将这些乘除运算后的整数值放回原表达式的相应位置,则随后整个表达式的值,就等于一系列整数加减后的值。基于此,我们可以用一个栈,保存这些(进行乘除运算后的)整数的值。
对于加减号后的数字,将其直接压入栈中;对于乘除号后的数字,可以直接与栈顶元素计算,并替换栈顶元素为计算后的结果具体来说,遍历字符串 ss,并用变量flag 记录每个数字之前的运算符,对于第一个数字,其之前的运算符视为加号。每次遍历到数字末尾时,根据 flag 来决定计算方式 加号: 将数字压入栈,减号: 将数字的相反数压入栈,乘除号: 计算数字与栈顶元素,并将栈顶元素替换为计算结果。代码实现中,若读到一个运算符,或者遍历到字符串末尾,即认为是遍历到了数字末尾。处理完该数字后,更新 flag 为当前遍历的字符遍历完字符串 ss 后,将栈中元素累加,即为该字符串表达式的值。
Character.isDigit() 这个函数是判断字符是否由数字组成
举例 : 2 * 5 s="2 * 5" s的长度=5
第一步 : num = 0 , flag = '+' , 遍历 i = 0 因为是数字所以 : num = 2
第二步 : 遍历 i = 1 , ' ' 不会进入循环
第三部 : 遍历 i = 2 , * 是乘号 所以进入到第二个分支里 , 因为默认的flag = '+' , 所以把2放到栈里 , 把符号flag = * , num = 0
第四步 : 遍历 i = 3 , ' ' 不会进入分支
第五步 : 遍历 i = 4 , num = 5 并且 i = n 所以进入第二个分支 , flag = * , 所以取出 2 * num = 2 * 5 = 10 , 把10放到栈里
解析 :
class Solution {
public int calculate(String s) {
Stack<Integer> stack = new Stack<>();
char flag = '+';
int num = 0;
int n = s.length() - 1;
for(int i =0 ; i <= n ; i++){
if(Character.isDigit(s.charAt(i))){
num = num * 10 + (s.charAt(i) - '0');
}
if(!Character.isDigit(s.charAt(i)) && s.charAt(i) != ' ' || i == n ){
switch(flag){
case '+' :
stack.push(num);
break;
case '-' :
stack.push(-1 * num);
break;
case '*' :
stack.push(stack.pop() * num);
break;
default :
stack.push(stack.pop() / num);
}
flag = s.charAt(i);
num = 0;
}
}
int val = 0;
while(!stack.isEmpty()){
val += stack.pop();
}
return val;
}
}
这关就到这里 , 下一关见!