227. 基本计算器 II 力扣链接
**题目要求:**给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。
整数除法仅保留整数部分。
你可以假设给定的表达式总是有效的。所有中间结果将在 [-231, 231 - 1] 的范围内。
注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。
本题是基础题,没有任何括号,相对简单一点
- 方法1:对不同计算符号设置不用优先级,然后使用两个栈分别存储操作符和数字,进行计算
注意:内层循环是while
class Solution {
public int calculate(String s) {
Map<Character,Integer> opsPrio=new HashMap<>();
Stack<Character> ops=new Stack<>();
Stack<Integer> number=new Stack<>();
opsPrio.put('+', 2);
opsPrio.put('-', 2);
opsPrio.put('*', 3);
opsPrio.put('/', 3);
s=s.replace(" ","");
for(int i=0;i<s.length();){
char c=s.charAt(i);
if(Character.isDigit(c)){
int num=0;
while(i<s.length()&&Character.isDigit(s.charAt(i))){
num=num*10+s.charAt(i)-'0';
i++;
}
number.push(num);
}else{
while(!ops.isEmpty() && opsPrio.get(c)<=opsPrio.get(ops.peek())){
calcul(ops,number);
}
ops.push(c);
i++;
}
}
while(!ops.isEmpty()){
calcul(ops,number);
}
return number.peek();
}
private void calcul(Stack<Character> ops,Stack<Integer> number){
if(ops.isEmpty()||number.size()<2)return;
char c=ops.pop();
int r=number.pop();
int l=number.pop();
int res=0;
if(c=='+'){
res=l+r;
}else if(c=='-'){
res=l-r;
}else if(c=='*'){
res=l*r;
}else{
res=l/r;
}
number.push(res);
}
}
- 方法2:一种基于单遍扫描的算法,使用一个栈来处理操作符和操作数。
class Solution {
public int calculate(String s) {
Stack<Integer> stack = new Stack<>();
int currentNumber = 0;
char operation = '+';
for (int i = 0; i < s.length(); i++) {
char currentChar = s.charAt(i);
if (Character.isDigit(currentChar)) {
currentNumber = currentNumber * 10 + (currentChar - '0');
}
if (!Character.isDigit(currentChar) && !Character.isWhitespace(currentChar) || i == s.length() - 1) {
if (operation == '+') {
stack.push(currentNumber);
} else if (operation == '-') {
stack.push(-currentNumber);
} else if (operation == '*') {
stack.push(stack.pop() * currentNumber);
} else if (operation == '/') {
stack.push(stack.pop() / currentNumber);
}
operation = currentChar;
currentNumber = 0;
}
}
int result = 0;
while (!stack.isEmpty()) {
result += stack.pop();
}
return result;
}
224. 基本计算器 力扣链接
**题目要求:**给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。
注意:不允许使用任何将字符串作为数学表达式计算的内置函数,比如 eval() 。
本题是包括了()在内的题目,相对更难一些。
- 方法:使用栈来处理操作数和操作符,并且支持括号的嵌套计算
class Solution {
public int calculate(String s) {
Stack<Integer> stack = new Stack<>();
int currentNumber = 0;
int result = 0; // For the ongoing total
int sign = 1; // 1 means positive, -1 means negative
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (Character.isDigit(c)) {
currentNumber = 0;
while (i < s.length() && Character.isDigit(s.charAt(i))) {
currentNumber = currentNumber * 10 + (s.charAt(i) - '0');
i++;
}
result += sign * currentNumber;
i--; // To offset the next i++ in the for loop
} else if (c == '+') {
sign = 1;
} else if (c == '-') {
sign = -1;
} else if (c == '(') {
// Push the result and sign onto the stack, for later
stack.push(result);
stack.push(sign);
// Reset result and sign for the new sub-expression
result = 0;
sign = 1;
} else if (c == ')') {
result = result * stack.pop() + stack.pop();
}
}
return result;
}
}
770. 基本计算器 IV 力扣链接
题目要求:
给定一个表达式如 expression = “e + 8 - a + 5” 和一个求值映射,如 {“e”: 1}(给定的形式为 evalvars = [“e”] 和 evalints = [1]),返回表示简化表达式的标记列表,例如 [“-1a",“14”]
表达式交替使用块和符号,每个块和符号之间有一个空格。
块要么是括号中的表达式,要么是变量,要么是非负整数。
变量是一个由小写字母组成的字符串(不包括数字)。请注意,变量可以是多个字母,并注意变量从不具有像 “2x” 或 “-x” 这样的前导系数或一元运算符 。
表达式按通常顺序进行求值:先是括号,然后求乘法,再计算加法和减法。
例如,expression = “1 + 2 * 3” 的答案是 [“7”]。
输出格式如下:
对于系数非零的每个自变量项,我们按字典排序的顺序将自变量写在一个项中。
例如,我们永远不会写像 “bac” 这样的项,只写 “abc”。
项的次数等于被乘的自变量的数目,并计算重复项。我们先写出答案的最大次数项,用字典顺序打破关系,此时忽略词的前导系数。
例如,"aabc” 的次数为 4。
项的前导系数直接放在左边,用星号将它与变量分隔开(如果存在的话)。前导系数 1 仍然要打印出来。
格式良好的一个示例答案是 [“-2aaa", "3aab”, “3bb”, “4a", "5c”, “-6”] 。
系数为 0 的项(包括常数项)不包括在内。
例如,“0” 的表达式输出为 [] 。
注意:你可以假设给定的表达式均有效。所有中间结果都在区间 [-231, 231 - 1] 内。
- 方法:使用递归下降解析来处理表达式并构建多项式表示
class Solution {
public List<String> basicCalculatorIV(String expression, String[] evalvars, int[] evalints) {
// Create a map for variable evaluation
Map<String, Integer> evalMap = new HashMap<>();
for (int i = 0; i < evalvars.length; i++) {
evalMap.put(evalvars[i], evalints[i]);
}
// Parse the expression and return the result as a list
return parse(expression, evalMap).toList();
}
private Poly parse(String expression, Map<String, Integer> evalMap) {
Stack<Poly> stack = new Stack<>();
Stack<Character> ops = new Stack<>();
int n = expression.length();
for (int i = 0; i < n; ) {
char c = expression.charAt(i);
if (c == ' ') {
i++;
} else if (c == '(') {
ops.push(c);
i++;
} else if (c == ')') {
while (ops.peek() != '(') {
stack.push(applyOp(stack.pop(), stack.pop(), ops.pop()));
}
ops.pop();
i++;
} else if (Character.isDigit(c) || Character.isLetter(c)) {
int j = i;
while (j < n && (Character.isDigit(expression.charAt(j)) || Character.isLetter(expression.charAt(j)))) {
j++;
}
String term = expression.substring(i, j);
i = j;
if (Character.isDigit(term.charAt(0))) {
stack.push(new Poly(Integer.parseInt(term)));
} else {
if (evalMap.containsKey(term)) {
stack.push(new Poly(evalMap.get(term)));
} else {
stack.push(new Poly(term, 1));
}
}
} else if (c == '+' || c == '-' || c == '*') {
while (!ops.isEmpty() && precedence(ops.peek()) >= precedence(c)) {
stack.push(applyOp(stack.pop(), stack.pop(), ops.pop()));
}
ops.push(c);
i++;
}
}
while (!ops.isEmpty()) {
stack.push(applyOp(stack.pop(), stack.pop(), ops.pop()));
}
return stack.pop();
}
private int precedence(char op) {
if (op == '+' || op == '-') return 1;
if (op == '*') return 2;
return 0;
}
private Poly applyOp(Poly b, Poly a, char op) {
if (op == '+') return a.add(b);
if (op == '-') return a.subtract(b);
if (op == '*') return a.multiply(b);
return new Poly();
}
class Poly {
Map<List<String>, Integer> terms;
Poly() {
terms = new HashMap<>();
}
Poly(int coeff) {
terms = new HashMap<>();
if (coeff != 0) {
terms.put(new ArrayList<>(), coeff);
}
}
Poly(String var, int coeff) {
terms = new HashMap<>();
if (coeff != 0) {
terms.put(new ArrayList<>(Arrays.asList(var)), coeff);
}
}
Poly add(Poly other) {
Poly res = new Poly();
for (List<String> key : this.terms.keySet()) {
res.terms.put(key, this.terms.getOrDefault(key, 0) + other.terms.getOrDefault(key, 0));
}
for (List<String> key : other.terms.keySet()) {
if (!this.terms.containsKey(key)) {
res.terms.put(key, other.terms.get(key));
}
}
return res;
}
Poly subtract(Poly other) {
Poly res = new Poly();
for (List<String> key : this.terms.keySet()) {
res.terms.put(key, this.terms.getOrDefault(key, 0) - other.terms.getOrDefault(key, 0));
}
for (List<String> key : other.terms.keySet()) {
if (!this.terms.containsKey(key)) {
res.terms.put(key, -other.terms.get(key));
}
}
return res;
}
Poly multiply(Poly other) {
Poly res = new Poly();
for (List<String> key1 : this.terms.keySet()) {
for (List<String> key2 : other.terms.keySet()) {
List<String> key = new ArrayList<>(key1);
key.addAll(key2);
Collections.sort(key);
int coeff = this.terms.get(key1) * other.terms.get(key2);
res.terms.put(key, res.terms.getOrDefault(key, 0) + coeff);
}
}
return res;
}
List<String> toList() {
List<String> res = new ArrayList<>();
List<List<String>> keys = new ArrayList<>(terms.keySet());
Collections.sort(keys, (a, b) -> {
if (a.size() != b.size()) return b.size() - a.size();
return a.toString().compareTo(b.toString());
});
for (List<String> key : keys) {
int coeff = terms.get(key);
if (coeff == 0) continue;
StringBuilder sb = new StringBuilder();
sb.append(coeff);
for (String var : key) {
sb.append('*').append(var);
}
res.add(sb.toString());
}
return res;
}
}
}