772. Basic Calculator III

LeetCode medium original: C# #csharp #hash-table #leetcode #math #medium #stack #string
O texto da tarefa é traduzido do russo para o idioma selecionado. O código permanece sem alterações.

Реализуйте базовый калькулятор для вычисления простого строкового выражения.

string выражения содержит только неотрицательные целые числа, операторы '+', '-', '*', '/' и открывающие '(' и закрывающие скобки ')'. Целочисленное деление должно округляться к нулю.

Предполагается, что данное выражение всегда корректно. Все промежуточные результаты будут находиться в диапазоне [-2^31, 2^31 - 1].

Примечание: нельзя использовать встроенные функции для вычисления строк как математических выражений, такие как eval().

Exemplo:

Input: s = "1+1"

Output: 2

C# solução

correspondente/original
public class Solution {
    private string Evaluate(char operator, string first, string second) {
        int x = int.Parse(first);
        int y = int.Parse(second);
        int res = 0;
        
        if (operator == '+') {
            res = x;
        } else if (operator == '-') {
            res = -x;
        } else if (operator == '*') {
            res = x * y;
        } else {
            res = x / y;
        }
        
        return res.ToString();
    }
    
    public int Calculate(string s) {
        Stack<string> stack = new Stack<string>();
        string curr = "";
        char previousOperator = '+';
        s += "@";
        HashSet<string> operators = new HashSet<string>(new string[] {"+", "-", "*", "/"});
        
        foreach (char c in s) {
            if (char.IsDigit(c)) {
                curr += c;
            } else if (c == '(') {
                stack.Push(previousOperator.ToString());
                previousOperator = '+';
            } else {
                if (previousOperator == '*' || previousOperator == '/') {
                    stack.Push(Evaluate(previousOperator, stack.Pop(), curr));
                } else {
                    stack.Push(Evaluate(previousOperator, curr, "0"));
                }
                
                curr = "";
                previousOperator = c;
                if (c == ')') {
                    int currentTerm = 0;
                    while (!operators.Contains(stack.Peek())) {
                        currentTerm += int.Parse(stack.Pop());
                    }
                    
                    curr = currentTerm.ToString();
                    previousOperator = stack.Pop()[0];
                }
            }
        }
        
        int ans = 0;
        foreach (string num in stack) {
            ans += int.Parse(num);
        }
        return ans;
    }
}

C++ solução

rascunho automático, revisar antes de enviar
#include <bits/stdc++.h>
using namespace std;

// Auto-generated C++ draft from the C# solution. Review containers, LINQ and helper types before submit.
class Solution {
public:
    private string Evaluate(char operator, string first, string second) {
        int x = int.Parse(first);
        int y = int.Parse(second);
        int res = 0;
        
        if (operator == '+') {
            res = x;
        } else if (operator == '-') {
            res = -x;
        } else if (operator == '*') {
            res = x * y;
        } else {
            res = x / y;
        }
        
        return res.ToString();
    }
    
    public int Calculate(string s) {
        stack<string> stack = new stack<string>();
        string curr = "";
        char previousOperator = '+';
        s += "@";
        HashSet<string> operators = new HashSet<string>(new string[] {"+", "-", "*", "/"});
        
        foreach (char c in s) {
            if (char.IsDigit(c)) {
                curr += c;
            } else if (c == '(') {
                stack.push(previousOperator.ToString());
                previousOperator = '+';
            } else {
                if (previousOperator == '*' || previousOperator == '/') {
                    stack.push(Evaluate(previousOperator, stack.pop(), curr));
                } else {
                    stack.push(Evaluate(previousOperator, curr, "0"));
                }
                
                curr = "";
                previousOperator = c;
                if (c == ')') {
                    int currentTerm = 0;
                    while (!operators.Contains(stack.Peek())) {
                        currentTerm += int.Parse(stack.pop());
                    }
                    
                    curr = currentTerm.ToString();
                    previousOperator = stack.pop()[0];
                }
            }
        }
        
        int ans = 0;
        foreach (string num in stack) {
            ans += int.Parse(num);
        }
        return ans;
    }
}

Java solução

correspondente/original
class Solution {
    private String evaluate(char operator, String first, String second) {
        int x = Integer.parseInt(first);
        int y = Integer.parseInt(second);
        int res = 0;
        
        if (operator == '+') {
            res = x;
        } else if (operator == '-') {
            res = -x;
        } else if (operator == '*') {
            res = x * y;
        } else {
            res = x / y;
        }
        
        return Integer.toString(res);
    }
    
    public int calculate(String s) {
        Stack<String> stack = new Stack<>();
        String curr = "";
        char previousOperator = '+';
        s += "@";
        Set<String> operators = new HashSet<>(Arrays.asList("+", "-", "*", "/"));
        
        for (char c: s.toCharArray()) {
            if (Character.isDigit(c)) {
                curr += c;
            } else if (c == '(') {
                stack.push("" + previousOperator);
                previousOperator = '+';
            } else {
                if (previousOperator == '*' || previousOperator == '/') {
                    stack.push(evaluate(previousOperator, stack.pop(), curr));
                } else {
                    stack.push(evaluate(previousOperator, curr, "0"));
                }
                
                curr = "";
                previousOperator = c;
                if (c == ')') {
                    int currentTerm = 0;
                    while (!operators.contains(stack.peek())) {
                        currentTerm += Integer.parseInt(stack.pop());
                    }
                    
                    curr = Integer.toString(currentTerm);
                    previousOperator = stack.pop().charAt(0);
                }
            }
        }
        
        int ans = 0;
        for (String num: stack) {
            ans += Integer.parseInt(num);
        }

        return ans;
    }
}

JavaScript solução

correspondente/original
class Solution {
    evaluate(operator, first, second) {
        const x = parseInt(first)
        const y = parseInt(second)
        let res = 0

        if (operator === '+') {
            res = x
        } else if (operator === '-') {
            res = -x
        } else if (operator === '*') {
            res = x * y
        } else {
            res = Math.trunc(x / y)
        }

        return res.toString()
    }

    calculate(s) {
        const stack = []
        let curr = ""
        let previousOperator = '+'
        s += "@"
        const operators = new Set(["+", "-", "*", "/"])

        for (const c of s) {
            if (/\d/.test(c)) {
                curr += c
            } else if (c === '(') {
                stack.push(previousOperator)
                previousOperator = '+'
            } else {
                if (previousOperator === '*' || previousOperator === '/') {
                    stack.push(this.evaluate(previousOperator, stack.pop(), curr))
                } else {
                    stack.push(this.evaluate(previousOperator, curr, "0"))
                }

                curr = ""
                previousOperator = c
                if (c === ')') {
                    let currentTerm = 0
                    while (!operators.has(stack[stack.length - 1])) {
                        currentTerm += parseInt(stack.pop())
                    }

                    curr = currentTerm.toString()
                    previousOperator = stack.pop()
                }
            }
        }

        let ans = 0
        for (const num of stack) {
            ans += parseInt(num)
        }

        return ans
    }
}

Python solução

correspondente/original
class Solution:
    def evaluate(self, operator, first, second):
        x = int(first)
        y = int(second)
        if operator == '+':
            return str(x)
        elif operator == '-':
            return str(-x)
        elif operator == '*':
            return str(x * y)
        else:
            return str(x // y)

    def calculate(self, s: str) -> int:
        stack = []
        curr = ""
        previousOperator = '+'
        s += "@"
        operators = set("+-*/")
        
        for c in s:
            if c.isdigit():
                curr += c
            elif c == '(':
                stack.append(previousOperator)
                previousOperator = '+'
            else:
                if previousOperator in "*/":
                    stack.append(self.evaluate(previousOperator, stack.pop(), curr))
                else:
                    stack.append(self.evaluate(previousOperator, curr, "0"))
                
                curr = ""
                previousOperator = c
                if c == ')':
                    currentTerm = 0
                    while stack[-1] not in operators:
                        currentTerm += int(stack.pop())
                    curr = str(currentTerm)
                    previousOperator = stack.pop()
        
        return sum(int(num) for num in stack)

Go solução

correspondente/original
package main

import (
    "strconv"
)

type Solution struct{}

func (sol *Solution) evaluate(operator byte, first, second string) string {
    x, _ := strconv.Atoi(first)
    y, _ := strconv.Atoi(second)
    res := 0

    if operator == '+' {
        res = x
    } else if operator == '-' {
        res = -x
    } else if operator == '*' {
        res = x * y
    } else {
        res = x / y
    }

    return strconv.Itoa(res)
}

func (sol *Solution) calculate(s string) int {
    stack := []string{}
    curr := ""
    previousOperator := byte('+')
    s += "@"
    operators := map[string]struct{}{"+": {}, "-": {}, "*": {}, "/": {}}

    for i := 0; i < len(s); i++ {
        c := s[i]
        if c >= '0' && c <= '9' {
            curr += string(c)
        } else if c == '(' {
            stack = append(stack, string(previousOperator))
            previousOperator = '+'
        } else {
            if previousOperator == '*' || previousOperator == '/' {
                top := stack[len(stack)-1]
                stack = stack[:len(stack)-1]
                stack = append(stack, sol.evaluate(previousOperator, top, curr))
            } else {
                stack = append(stack, sol.evaluate(previousOperator, curr, "0"))
            }

            curr = ""
            previousOperator = c
            if c == ')' {
                currentTerm := 0
                for len(stack) > 0 {
                    top := stack[len(stack)-1]
                    if _, ok := operators[top]; ok {
                        break
                    }
                    stack = stack[:len(stack)-1]
                    val, _ := strconv.Atoi(top)
                    currentTerm += val
                }
                curr = strconv.Itoa(currentTerm)
                previousOperator = stack[len(stack)-1][0]
                stack = stack[:len(stack)-1]
            }
        }
    }

    ans := 0
    for _, num := range stack {
        val, _ := strconv.Atoi(num)
        ans += val
    }

    return ans
}

func main() {}

Algorithm

Определите вспомогательную функцию evaluate, которая принимает оператор и numberвые аргументы. Заметьте, что эта функция идентична той, что представлена в подходе "Basic Calculator II". Инициализируйте несколько переменных: стек для хранения промежуточных результатов, curr для отслеживания текущего числа, которое мы строим, и previousOperator для отслеживания предыдущего оператора. Добавьте в строку s случайный символ, который не будет появляться во Entradaных данных, наExemplo "@".

Итерация по Entradaным данным. Для каждого символа c: если c является цифрой, добавьте его к curr. В противном случае, если c == '(', мы начинаем вычисление нового изолированного выражения. В этом случае сохраните previousOperator в стек и установите previousOperator = "+".

Если c является оператором, то необходимо вычислить значение curr. Используйте функцию evaluate, чтобы применить previousOperator к curr, и добавьте результат в стек. Затем сбросьте curr до нуля и обновите previousOperator = c. Если c == ')', это означает, что мы находимся в конце изолированного выражения и должны полностью его вычислить. Извлекайте из стека до тех пор, пока не достигнете оператора, суммируя все извлеченные числа в curr. Как только достигнете оператора, обновите previousOperator = stack.pop(). return сумму всех чисел в стеке.

😎

Vacancies for this task

vagas ativas with overlapping task tags are mostradas.

Todas as vagas
Ainda não há vagas ativas.