1. 程式人生 > >[LeetCode] Basic Calculator 基本計算器

[LeetCode] Basic Calculator 基本計算器

Implement a basic calculator to evaluate a simple expression string.

The expression string may contain open ( and closing parentheses ), the plus + or minus sign -, non-negative integers and empty spaces .

You may assume that the given expression is always valid.

Some examples:

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

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

這道題讓我們實現一個基本的計算器來計算簡單的算數表示式,而且題目限制了表示式中只有加減號,數字,括號和空格,沒有乘除,那麼就沒啥計算的優先順序之分了。於是這道題就變的沒有那麼複雜了。我們需要一個棧來輔助計算,用個變數sign來表示當前的符號,我們遍歷給定的字串s,如果遇到了數字,由於可能是個多位數,所以我們要用while迴圈把之後的數字都讀進來,然後用sign*num來更新結果res;如果遇到了加號,則sign賦為1,如果遇到了符號,則賦為-1;如果遇到了左括號,則把當前結果res和符號sign壓入棧,res重置為0,sign重置為1;如果遇到了右括號,結果res乘以棧頂的符號,棧頂元素出棧,結果res加上棧頂的數字,棧頂元素出棧。程式碼如下:

解法一:

class Solution {
public:
    int calculate(string s) {
        int res = 0, sign = 1, n = s.size();
        stack<int> st;
        for (int i = 0; i < n; ++i) {
            char c = s[i];
            if (c >= '0') {
                int num = 0;
                while (i < n && s[i] >= '
0') { num = 10 * num + s[i++] - '0'; } res += sign * num; --i; } else if (c == '+') { sign = 1; } else if (c == '-') { sign = -1; } else if (c == '(') { st.push(res); st.push(sign); res = 0; sign = 1; } else if (c == ')') { res *= st.top(); st.pop(); res += st.top(); st.pop(); } } return res; } };

下面這種方法和上面的基本一樣,只不過對於數字的處理略微不同,上面的方法是連續讀入數字,而這種方法是使用了一個變數來儲存讀入的num,所以在遇到其他字元的時候,都要用sign*num來更新結果res,參見程式碼如下:

解法二:

class Solution {
public:
    int calculate(string s) {
        int res = 0, num = 0, sign = 1, n = s.size();
        stack<int> st;
        for (int i = 0; i < n; ++i) {
            char c = s[i];
            if (c >= '0') {
                num = 10 * num + (c - '0');
            } else if (c == '+' || c == '-') {
                res += sign * num;
                num = 0;
                sign = (c == '+') ? 1 : -1;
             } else if (c == '(') {
                st.push(res);
                st.push(sign);
                res = 0;
                sign = 1;
            } else if (c == ')') {
                res += sign * num;
                num = 0;
                res *= st.top(); st.pop();
                res += st.top(); st.pop();
            }
        }
        res += sign * num;
        return res;
    }
};

在做了Basic Calculator III之後,再反過頭來看這道題,發現遞迴處理括號的方法在這道題也同樣適用,我們用一個變數cnt,遇到左括號自增1,遇到右括號自減1,當cnt為0的時候,說明括號正好完全匹配,這個trick在驗證括號是否valid的時候經常使用到。然後我們就是根據左右括號的位置提取出中間的子字串呼叫遞迴函式,返回值賦給num,參見程式碼如下:

解法三:

class Solution {
public:
    int calculate(string s) {
        int res = 0, num = 0, sign = 1, n = s.size();
        for (int i = 0; i < n; ++i) {
            char c = s[i];
            if (c >= '0' && c <= '9') {
                num = 10 * num + (c - '0');
            } else if (c == '(') {
                int j = i, cnt = 0;
                for (; i < n; ++i) {
                    if (s[i] == '(') ++cnt;
                    if (s[i] == ')') --cnt;
                    if (cnt == 0) break;
                }
                num = calculate(s.substr(j + 1, i - j - 1));
            }
            if (c == '+' || c == '-' || i == n - 1) {
                res += sign * num;
                num = 0;
                sign = (c == '+') ? 1 : -1;
             } 
        }
        return res;
    }
};

類似題目:

參考資料: