Basic Calculator II

Problem

Implement a basic calculator to evaluate a simple expression string.

The expression string contains only non-negative integers, +, -, *, / operators and empty spaces . The integer division should truncate toward zero.

You may assume that the given expression is always valid.

Some examples:

"3+2*2" = 7
" 3/2 " = 1
" 3+5 / 2 " = 5

Note: Do not use the evil built-in library function.

Solution

O(n) time using Stack

public class Solution {
    public int calculate(String s) {
        if (s == null || s.length() == 0) return 0;
        String str = s.trim().replaceAll(" +", "");
        int len = str.length();
        Stack<Integer> stack = new Stack<>();
        int num = 0, sign = '+';
        for (int i = 0; i < len; i++) {
            char c = str.charAt(i);
            if (Character.isDigit(c)) num = num * 10 + (c - '0');
            if (!Character.isDigit(c) || i == len - 1) {
                switch (sign) {
                    case '+':
                        stack.push(num);
                        break;
                    case '-':
                        stack.push(-num);
                        break;
                    case '*':
                        stack.push(stack.pop() * num);
                        break;
                    case '/':
                        stack.push(stack.pop() / num);
                        break;
                }
                sign = c;
                num = 0;
            }
        }
        int res = 0;
        for (int i : stack) res += i;
        return res;
    }
}

O(n) time O(1) space no Stack solution

public class Solution {
    public int calculate(String s) {
        if (s == null || s.length() == 0) return 0;
        String str = s.trim().replaceAll(" +", "");
        int len = str.length();
        int res = 0, preVal = 0, num = 0, sign = '+';
        for (int i = 0; i < len; i++) {
            char c = str.charAt(i);
            if (Character.isDigit(c)) num = num * 10 + (c - '0');
            if (!Character.isDigit(c) || i == len - 1) { //Must handle the last index using previous "sign" 
                switch (sign) {
                    case '+':
                        res += preVal;
                        preVal = num;
                        break;
                    case '-':
                        res += preVal;
                        preVal = -num;
                        break;
                    case '*':
                        preVal *= num;
                        break;
                    case '/':
                        preVal /= num;
                        break;
                }
                sign = c;
                num = 0;
            }
        }
        res += preVal;
        return res;
    }
}

Analysis

This problem is tricky if you are not very careful with number and sign
The basic idea to solve this problem is that we have a reference to the number before we meet sign
Then according to the sign we encounter, we do some calculations and update the num, sign or res

First solution uses stack to store the previous number
When the current character is not digit or is the last one, we update the stack corresponding to the sign
Then we update the sign with current character and reset num to 0
At the end, we go through all numbers from stack and simply add them together to get our result

The second solution is using the similar idea but having a var preVal as role of stack
We only update the res if sign is + or -, when it's * or / we just update preVal
At the end, we also need to update the res with preVal

Notice that, we call s.trim() to remove the leading and trailing space
Then we use replaceAll(" +", "") to remove the space in the middle spaces Actually we can just simply use replaceAll() but I want you to get familiar with trim() method ;)

results matching ""

    No results matching ""