Resolver una expresión aritmética de cuatro es un problema clásico cuando estudiamos "Estructura de datos (pila)". Y ahora, intentamos romper con el uso de la pila e implementar una aritmética de cuatro con el mismo código hermoso.
A continuación, procederemos paso a paso, comenzando con la calculadora de suma y resta más simple, sumando multiplicaciones y divisiones, sumando paréntesis y finalmente presentaremos una calculadora aritmética completa de cuatro. ¡Empecemos> _ <! ! !
Calculadora básica 1-solo suma y resta
entrada: "2 + 3 + 11-6"
salida: 10
La primera pregunta implica una idea importante de este tipo de problema: las cuatro operaciones aritméticas pueden considerarse operaciones de suma.
Es fácil de entender mirando la imagen:
Ahora considere una pregunta extremadamente importante: ¿Cuál es la base para dividir operaciones de suma y resta en operaciones de suma en la figura anterior? En otras palabras, cuando pasamos a qué carácter, ¿sabemos que un elemento de suma completa debe segmentarse en este momento?
¿Es un número? Cuando lo atravesamos +
, registramos este símbolo; luego lo atravesamos 3
y el resultado final es +3. Parece una idea correcta, pero cuando 1
se alcanza el recorrido , el programa cree erróneamente que la suma y la división ha terminado, y suma +1 al resultado final, pero en realidad debería ser +11.
La división se basa en el signo más / menos. Después de comprender este punto, la idea de esta pregunta está lista para surgir: establecemos un ops
búfer para el llamado último símbolo, establecemos un num
registro del número actual y establecemos uno res
como resultado final; cuando c
el número es atravesado, se registra; cuando el c
recorrido alcanza el signo más / menos puesto en un elemento de adición (a ops
y num
composición) se agrega al resultado final; también c
apunta a más / menos el caché ops
, se convierte en un símbolo que c
continúa moviéndose.
También tenga en cuenta, ¿el último elemento de adición no está dividido? Porque no hay ningún símbolo detrás. Por lo tanto, cuando se recorre hasta el último carácter ( len - 1
), también se utiliza como base para dividir el elemento de adición.
Todavía mira la imagen para entender:
El código se proporciona a continuación (además, 11
el manejo de varios dígitos ( ) en este código es muy elegante, preste atención a la experiencia):
class Solution {
public int calculate(String s) {
int num = 0; // 记录的数字(看看它在上图中的位置)
char ops = '+'; // 缓存的符号(看看它在上图中的位置)
int res = 0; // 最终结果
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// 如果是数字
if (Character.isDigit(c)) {
num = num * 10 + c - '0';
}
// 如果是加减
if (c == '+' || c == '-' || i == s.length() - 1) {
switch (ops) {
case '+': res += num; break;
case '-': res -= num; break;
}
num = 0;
ops = c;
}
}
return res;
}
}
Calculadora básica 2-suma, resta, multiplicación y división
entrada: "2-3 + 4 * 6 + 2"
salida: 25
Debería poder darse cuenta de inmediato, ¿qué es más que una suma y una resta? prioridad.
No hablemos de prioridad por ahora, primero pensemos si la suma, resta, multiplicación y división se pueden dividir en términos de suma. No solo eso, sino que a partir de la siguiente división, puede comprender mejor por qué la división se basa en números, no en los signos de multiplicación / división, sino en los signos más / menos.
Todavía mira la imagen:
El problema de prioridad se resuelve a continuación. No es difícil encontrar que lo anterior +4
no se puede apresurar para agregarlo res
, por lo que también necesitamos un resultado en caché tmp
; cuando se recorre para sumar / restar / multiplicar / dividir, tmp
se calcula el último símbolo y el símbolo actual se almacena en caché; solo el transversal al signo más / Solo cuando se agrega el signo menos, la caché se tmp
agrega al resultado final res
.
Todavía mira la imagen:
El código se proporciona a continuación:
class Solution {
public int calculate(String s) {
int num = 0; // 记录的数字
char ops = '+'; // 缓存的符号
int tmp = 0; // 缓存结果
int res = 0; // 最终结果
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// 如果是数字
if (Character.isDigit(c)) {
num = num * 10 + c - '0';
}
// 如果是符号
if (c == '+' || c == '-' || c == '*' || c == '/' || i == s.length() - 1) {
switch (ops) {
case '+': tmp += num; break;
case '-': tmp -= num; break;
case '*': tmp *= num; break;
case '/': tmp /= num; break;
}
if (c == '+' || c == '-' || i == s.length() - 1) {
res += tmp;
tmp = 0;
}
num = 0;
ops = c;
}
}
return res;
}
}
Calculadora básica 3-suma y resta con paréntesis
entrada: "2- (4- (7 + 1))"
salida: 6
¿No es esto también una cuestión de prioridad? ¿Pueden los paréntesis elevar cualquier operación a la máxima prioridad?
No es. Los paréntesis se pueden anidar. Entonces este es un problema recursivo.
Seamos más violentos y cortemos la cuerda directamente. Al pasar a los paréntesis, el cnt
recuento se utiliza para coincidir con los paréntesis (cuando se encuentra el paréntesis izquierdo, el recuento aumenta en uno; cuando se encuentra el paréntesis derecho, el recuento se reduce en uno); cuando cnt
vuelve a 0, el contenido dentro del paréntesis más grande se usa como una nueva expresión. Se realiza la recursividad y se asigna el resultado del cálculo devuelto por la recursividad num
.
Todavía mira la imagen:
El código se proporciona a continuación (sobre la base del código básico de la calculadora 1, se agrega el tratamiento de paréntesis):
class Solution {
public int calculate(String s) {
int num = 0; // 记录的数字
char ops = '+'; // 缓存的符号
int res = 0; // 最终结果
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// 如果是括号
if (c == '(') {
int cnt = 0;
int t = i;
for (; i < s.length(); i++) {
if (s.charAt(i) == '(') cnt++;
if (s.charAt(i) == ')') cnt--;
if (cnt == 0) {
break;
}
}
num = calculate(s.substring(t + 1, i));
}
// 如果是数字
if (Character.isDigit(c)) {
num = num * 10 + c - '0';
}
// 如果是加减
if (c == '+' || c == '-' || i == s.length() - 1) {
switch (ops) {
case '+': res += num; break;
case '-': res -= num; break;
}
num = 0;
ops = c;
}
}
return res;
}
}
Calculadora básica 4-cuatro aritmética (suma, resta, multiplicación y división con paréntesis)
Combinando todos los pensamientos anteriores:
1) Cuatro operaciones aritméticas se pueden considerar como elementos de suma múltiple
2) La base para dividir elementos de suma no son números, ni signos de multiplicación / división, ni paréntesis, sino signos más / menos
3) Recorrer al número, sin registro cerebral; Recorrer al símbolo, calcular el símbolo anterior
3) Los problemas de prioridad causados por la multiplicación y la división se resuelven con resultados almacenados en caché
4) El problema de prioridad causado por los paréntesis se resuelve con una cadena recursiva
Y algunos detalles para hacer el código más elegante y robusto:
1) El último carácter también se utiliza como signo para cortar y agregar elementos.
2) Procesamiento de varios dígitos
3) Tratamiento de caracteres vacíos en expresiones
el código se muestra a continuación:
class Solution {
public int calculate(String s) {
int num = 0; // 当前的数字
char ops = '+'; // 当前的数字之前的符号
int tmp = 0; // 临时结果
int res = 0; // 最终结果
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// 如果是括号
if (c == '(') {
int cnt = 0;
int t = i;
for (; i < s.length(); i++) {
if (s.charAt(i) == '(') cnt++;
if (s.charAt(i) == ')') cnt--;
if (cnt == 0) {
break;
}
}
num = calculate(s.substring(t + 1, i));
}
// 如果是数字
if (Character.isDigit(c)) {
num = num * 10 + c - '0';
}
// 如果是符号
if (c == '+' || c == '-' || c == '*' || c == '/' || i == s.length() - 1) {
switch (ops) {
case '+': tmp += num; break;
case '-': tmp -= num; break;
case '*': tmp *= num; break;
case '/': tmp /= num; break;
}
if (c == '+' || c == '-' || i == s.length() - 1) {
res += tmp;
tmp = 0;
}
num = 0;
ops = c;
}
}
return res;
}
}
L oli Loli L o l i is esyo es elt h e MEJOR MEJORB E S T y yun n d preciosasP R E C I O U S obsequio regalog i f t eni n el lat h e mundo. mundo.w o r l d .