zoukankan      html  css  js  c++  java
  • Basic Calculator

    本博客介绍leetcode上的一道不难,但是比较经典的算法题。

    题目如下:

    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:

    也可以直接参考 https://leetcode.com/problems/basic-calculator/

    这是简单的加减计算运算题,一个直观的思路是运用栈,以及用后缀表达式求值。实现这一种算法,需要构造两个栈,分别是运算符栈和数字栈,然后将输入的中序表达式在转化为后续表达式的过程中求值。

    考虑到这道题目的特殊性,运算符只有加减和括号,我们可以转化加减运算符为(±1),这样可以省略计算时的判断语句,而直接将转化后的运算符数作为被加(减)数的系数

    这是我的代码

    int calculate(string s) {
        s.push_back('#');       //防止栈溢出
        stack<int>num;          //数字栈
        stack<int>oper;         //运算符栈
        for(int i=0; i<s.length()-1;++i)
        {
            if(isdigit(s[i]))   //判断数字,压入数字栈
            {
                int temp = s[i]-'0';
                while(++i && isdigit(s[i]))
                {
                    temp = temp * 10 + s[i] - '0'; 
                }
                num.push(temp);
            }
            switch (s[i]){       
            case '(':           //'('直接压入栈,其代表数为0
                oper.push(0);
                break;
            case '+':
            case '-':
                if(!oper.empty() && oper.top() != 0)      //栈中有加减运算符,则先弹出,再压入现在的运算符
                {
                    int num1 = num.top(); num.pop();
                    int num2 = num.top(); num.pop();
                    num.push(num2 + num1 * oper.top());
                    oper.pop();
                }
                if(s[i] == '-')
                    oper.push(-1);
                else oper.push(1);
                break;
            case ')':                       //为')',则一直弹出栈至弹出第一个'('
                if(oper.top() == 0)
                    oper.pop();
                else
                {
                    int num1 = num.top(); num.pop();
                    int num2 = num.top(); num.pop();
                    num.push(num2 + num1 * oper.top());
                    oper.pop();
                    oper.pop();
                }
                break;
            case '#':
                break;
            }
        }
        if(oper.empty())
                return num.top();
            else
            {
                int num1 = num.top(); num.pop();
                int num2 = num.top(); num.pop();
                return (num2 + num1 * oper.top());
            }
    }

    其实这个算法的效率并不是很高,原因在于,每个数字都要压栈、退栈,每个操作符(除了')')也同样如此。

    下面这个算法是讨论区上面的比较优秀的算法,其亮点是

    1. 用独立的变量存储上次的数字和加减运算符,在n次连续加减运算时省略了分别n-1次出入栈;
    2. 遇到'(',只压入前面的加减运算符,默认为加法。
    class Solution {
    public:
        int calculate(string s) {
            stack <int> nums, ops;
            int num = 0;
            int rst = 0;
            int sign = 1;
            for (char c : s) { 
                if (isdigit(c)) {
                    num = num * 10 + c - '0';
                }
                else {
                    rst += sign * num;
                    num = 0;
                    if (c == '+') sign = 1;
                    if (c == '-') sign = -1;
                    if (c == '(') {
                        nums.push(rst);
                        ops.push(sign);
                        rst = 0;
                        sign = 1;
                    }
                    if (c == ')' && ops.size()) {
                        rst = ops.top() * rst + nums.top();
                        ops.pop(); nums.pop();
                    }
                }
            }
            rst += sign * num;
            return rst;
        }
    };

    也可以参考https://leetcode.com/discuss/53921/16-ms-solution-in-c-with-stacks

  • 相关阅读:
    【BZOJ 4581】【Usaco2016 Open】Field Reduction
    【BZOJ 4582】【Usaco2016 Open】Diamond Collector
    【BZOJ 4580】【Usaco2016 Open】248
    【BZOJ 3754】Tree之最小方差树
    【51Nod 1501】【算法马拉松 19D】石头剪刀布威力加强版
    【51Nod 1622】【算法马拉松 19C】集合对
    【51Nod 1616】【算法马拉松 19B】最小集合
    【51Nod 1674】【算法马拉松 19A】区间的价值 V2
    【BZOJ 2541】【Vijos 1366】【CTSC 2000】冰原探险
    【BZOJ 1065】【Vijos 1826】【NOI 2008】奥运物流
  • 原文地址:https://www.cnblogs.com/zhx14/p/4916089.html
Copyright © 2011-2022 走看看