224. Basic Calculator ๐Ÿงฎ

Difficulty: Hard - Tags: Stack, Mathematical Expression

LeetCode Problem Link


Problem Statement ๐Ÿ“œ

Given a string s representing a valid expression, implement a basic calculator to evaluate it and return the result of the evaluation.

Constraints:

  • You are not allowed to use any built-in function which evaluates strings as mathematical expressions, such as eval().

Examples ๐ŸŒŸ

๐Ÿ”น Example 1:

Input:

s = "1 + 1"

Output:

2

๐Ÿ”น Example 2:

Input:

s = " 2-1 + 2 "

Output:

3

๐Ÿ”น Example 3:

Input:

s = "(1+(4+5+2)-3)+(6+8)"

Output:

23

Constraints โš™๏ธ

  • 1 <= s.length <= 3 * 10^5

  • s consists of digits, '+', '-', '(', ')', and spaces ' '.

  • s represents a valid expression.

  • '+' is not used as a unary operation (e.g., "+1" and "+(2 + 3)" are invalid).

  • '-' can be used as a unary operation (e.g., "-1" and "- (2 + 3)" are valid).

  • There will be no two consecutive operators in the input.

  • Every number and running calculation will fit in a signed 32-bit integer.


Solution ๐Ÿ’ก

To solve the problem, we need to handle:

  1. Parentheses: We need to evaluate expressions within parentheses first.

  2. Unary Minus: Handle negative numbers or expressions that start with a minus sign.

  3. Operators: Handle addition and subtraction between numbers.

We will use a stack to handle nested parentheses and the accumulation of results as we process the string.


Approach:

  1. Iterate through the string:

    • If we encounter a number, accumulate it and push it onto the stack.

    • If we encounter an operator (+ or -), record it for the next number.

    • If we encounter a parenthesis (, push the current result and operator onto the stack and start a new scope.

    • If we encounter a closing parenthesis ), calculate the result for that scope and return to the previous context.

  2. Handle each number:

    • Consider negative numbers and numbers with multiple digits.

  3. Handle operators:

    • For each operator, perform the addition or subtraction with the previous number or the current number if no previous number exists.


Java Solution

import java.util.Stack;

class Solution {
    public int calculate(String s) {
        Stack<Integer> stack = new Stack<>();
        int result = 0, sign = 1, num = 0; // result = accumulated result, sign = current sign (+ or -)

        for (char c : s.toCharArray()) {
            if (Character.isDigit(c)) {
                num = num * 10 + (c - '0'); // Build the number digit by digit
            } else if (c == '+') {
                result += sign * num; // Add the current number to the result
                num = 0; // Reset the number for the next iteration
                sign = 1; // Set the sign to + for the next number
            } else if (c == '-') {
                result += sign * num; // Add the current number to the result
                num = 0; // Reset the number for the next iteration
                sign = -1; // Set the sign to - for the next number
            } else if (c == '(') {
                stack.push(result); // Save the current result before going into the parentheses
                stack.push(sign); // Save the current sign
                result = 0; // Reset the result for the new expression inside parentheses
                sign = 1; // Reset the sign for the new expression
            } else if (c == ')') {
                result += sign * num; // Add the current number to the result
                num = 0; // Reset the number
                result *= stack.pop(); // Apply the sign from the last '('
                result += stack.pop(); // Add the previous result from before '('
            }
        }

        if (num != 0) { // Add the last number if any
            result += sign * num;
        }

        return result;
    }
}

Explanation of the Solution

  1. Building the Number: As we iterate through the string, we build numbers by accumulating digits.

  2. Sign Management: When encountering a + or -, we set the sign accordingly. If it's +, we add the current number to the result; if it's -, we subtract it.

  3. Parentheses Handling:

    • When encountering a (, we push the current result and sign onto the stack and reset them for the new expression inside the parentheses.

    • When encountering a ), we complete the evaluation of the expression inside the parentheses by applying the sign and adding the result to the previous context.

  4. Final Calculation: After the loop, we add any remaining number to the result.


Time Complexity โณ

  • O(n): We iterate over the string once, where n is the length of the string.

Space Complexity ๐Ÿ’พ

  • O(n): In the worst case, we might need space for the stack that stores the results and signs of nested parentheses.

You can find the full solution here.

Last updated