[Stack] [leetcode] [Medium] 227. Basic Calculator II

topic:

Implement a basic calculator to calculate the value of a simple string expression.

String expressions only contain non-negative integers, +, -, *, / four operators and spaces. Integer division only retains the integer part.

Example:

Input: "3+2*2"
Output: 7

source:

227. Basic Calculator II

Problem-solving ideas: stack

Because there are only additions, subtractions, multiplications and divisions and positive integers, the judgment logic is relatively simple.

Define two stacks, one for numbers, the other for operators and only +-operators.

Put the first number on the stack, traverse the following string, the operator and the number will appear in pairs.

  • If it is a plus and minus sign, the number is pushed onto the stack, and the operator is pushed onto the stack
  • If it is a multiplication and division sign, the top number of the stack is calculated with the new number and the top number of the stack is modified

Finally, the stack of operators is traversed, and addition or subtraction is calculated in order from beginning to end.

c code:

Use an array to implement the stack, pay attention to the stack size, and pay attention to int out of bounds.

char *get(char *s, long *n) {
    char *p = s;
    while (*p == ' ') p++;
    *n = 0;
    while (*p >= '0' && *p <= '9') {
        *n = *n * 10 + *p - '0';
        p++;
    }
    while (*p == ' ') p++;
    return p;
}

// +-*/正整数
int calculate(char * s) {
    long num[210000];
    char opt[210000];
    int topn = -1;
    int topo = -1;

    long n = 0;
    char *p = get(s, &n);
    num[++topn] = n;
    while (*p != 0) {
        char ch = *p;
        p = get(p+1, &n);
        if (ch == '*') {
            num[topn] *= n;
        } else if (ch == '/') {
            num[topn] /= n;
        } else {
            num[++topn] = n;
            opt[++topo] = ch;
        }
    }

    long ret = num[0];
    for (int i = 0; i <= topo; i++) {
        if (opt[i] == '+') {
            ret += num[i+1];
        } else {
            ret -= num[i+1];
        }
    }
    return ret;
}

I thought that the space consumption was very large, but it was not large in terms of the result.

Optimization idea 1:

Because there are no brackets, there is no need for a lot of storage space.

When the number of operators is equal to 2, the numbers in the stack can be merged. Because there are only 3 numbers in the stack at this time, and these 3 numbers are in addition and subtraction relationship, it is possible and only to merge the first and second numbers.

The code after optimization is as follows:

char *get(char *s, long *n) {
    char *p = s;
    while (*p == ' ') p++;
    *n = 0;
    while (*p >= '0' && *p <= '9') {
        *n = *n * 10 + *p - '0';
        p++;
    }
    while (*p == ' ') p++;
    return p;
}

// +-*/正整数
int calculate(char * s) {
    long num[3];
    char opt[2];
    int topn = -1;
    int topo = -1;

    long n = 0;
    char *p = get(s, &n);
    num[++topn] = n;
    while (*p != 0) {
        char ch = *p;
        p = get(p+1, &n);
        if (ch == '*') {
            num[topn] *= n;
        } else if (ch == '/') {
            num[topn] /= n;
        } else {
            num[++topn] = n;
            opt[++topo] = ch;
            if (topo == 1) {
                // 合并第一个和第二个数字
                if (opt[0] == '+') {
                    num[0] += num[1];
                } else {
                    num[0] -= num[1];
                }
                num[1] = num[2];
                topn = 1;
                opt[0] = opt[1];
                topo = 0;
            }
        }
    }

    long ret = num[0];
    for (int i = 0; i <= topo; i++) {
        if (opt[i] == '+') {
            ret += num[i+1];
        } else {
            ret -= num[i+1];
        }
    }
    return ret;
}

operation result:

Optimization idea 2:

The above code is still very complicated, so I optimized it again.

The idea of ​​optimization is:

1. When the sign is -, the number becomes negative, and the minus sign becomes a plus sign, so the second stack is all plus signs, and there is no need to exist.

2. Because the first stack only needs 3 spaces: one to store the previous result, one to store the top element of the stack, one to store the new number, and three variables can be defined. In order to remove the pointer at the top of the stack, just change the string s to 0+s to ensure that the pointer always points to the top of the stack.

The optimized code is as follows:

char *get(char *s, long *n) {
    char *p = s;
    while (*p == ' ') p++;
    *n = 0;
    while (*p >= '0' && *p <= '9') {
        *n = *n * 10 + *p - '0';
        p++;
    }
    while (*p == ' ') p++;
    return p;
}

int calculate(char * s) {
    long ret = 0, top = 0;

    char *p = get(s, &top); // 将第一个数字放入栈顶top
    while (*p != 0) {
        char ch = *p;
        long n = 0;
        p = get(p+1, &n);
        if (ch == '*') {
            top *= n;
        } else if (ch == '/') {
            top /= n;
        } else {
            if (ch == '-') n = 0 - n;
            ret += top;
            top = n;
        }
    }
    return ret + top;
}

The article has been revised many times, and it should not be revised again until now, unless other ideas for solving the problem are found. A product needs to be tempered many times to get closer to perfection.

Guess you like

Origin blog.csdn.net/hbuxiaoshe/article/details/114635663