772. Basic Calculator III

LeetCode medium original: C# #csharp #hash-table #leetcode #math #medium #stack #string
Le texte du problème est traduit du russe pour la langue sélectionnée. Le code reste inchangé.

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

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

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

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

Exemple:

Input: s = "1+1"

Output: 2

C# solution

correspondant/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++ solution

brouillon automatique, à relire avant soumission
#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 solution

correspondant/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 solution

correspondant/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 solution

correspondant/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 solution

correspondant/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 случайный символ, который не будет появляться во Entréeных данных, наExemple "@".

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

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

😎

Vacancies for this task

offres actives with overlapping task tags are affichés.

Toutes les offres
Il n'y a pas encore d'offres actives.