224. 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```
就是把这个字符串解析成一个式子然后算出结果。运算只有加减法,也没有负数,优先级比较好搞。有括号先算括号里面的。C语言书里头讲过可以用栈。这里的括号,我自然地想到了递归。“)”是递归的终止条件。遇到右括号就相当于括号里的东西处理完返回括号里头的结果。为了方便处理,把输入的字符串最后加上了一个“)”,这样递归的终止条件就不用再加一个判断字符串结束了。
从头开始读字符串,边读边解析。分几情况:
1,正负号,整形op表示符号。减法乘以-1也转化为加法。
2,数字,解析出来压到存运算数的vector里去。
3,左括号,开始递归调用这个函数,表示要先算括号里面的。
括号里的运算出结果就把它压到运算数的向量里头。(运算数的来源就三种,从字符串解析出来,和括号里的值算出来,运算数的vector进行运算的结果。)
4,右括号,说明函数该就结束了。
只要现在存这两个运算数,就可以做运算了。
代码如下:(递归)
```cpp
class Solution {
public:
    int calculate(string s) {
        //递归
        int index = 0;
        s += ')';
        int res = calucateBrackets(s,index);
        return res;
    }
private:
    //计算括号里面的值
    int calucateBrackets(string &s,int &index)
    {
        vector<int> num; //数
        int op = 0; //运算符  +1 -1 
        for(index; s[index] != ')'; index++)
        {
            if(s[index] == ' ')//空格,跳过
                continue;
            if(s[index] == '+')//正负号
            {
                op = 1;
                continue;
            }
            else if(s[index] == '-')
            {
                op = -1;
                continue;
            }
            if(s[index] >= '0' && s[index] <= '9')//数字
            {
                int value = parseInt(s,index);
                num.push_back(value);//把这数放进去
            }
            else if(s[index] == '(')//如果是左括号,递归算括号里面的
            {
                index++;
                int res = calucateBrackets(s,index);
                num.push_back(res);
            }
            if(num.size() == 2)
            {
                int a = num[0];
                int b = num[1];
                num.clear();
                num.push_back(a + op*b);
            }
        }
        return num[0];
    }
    //连读一个数
    int parseInt(string &s, int &index)
    {
        int res = 0;
        while(s[index] >= '0' && s[index] <= '9')
        {
            res*= 10;
            res+= (s[index] - '0');
            index++;
        }
        index--;
        return res;
    }
};

也可以不用递归算这个。
if else 大法好。。。
两个栈,一个存运算符,一个存运算数。“+”存1,“-”存-1,“(”存0,当个分界符。遇到“)”就弹栈,算,算到运算符栈有个0相当于算完一个括号。用栈的话是从后往前算。要是前头有负号就会出错了。(就像1-2+3,从后往前算相当于1-(2+3)所以,遇到负号就把它算掉。。)
代码如下:(非递归)

class Solution {
public:
    int calculate(string s) {
        int index = 0;
        if(s.size() == 0)
            return 0;
        vector<int> num; //数
        vector<int> op; 
        op.push_back(0);
        //操作符   + 1  - -1  ( 2  
        //stack<int> num; //数
        //stack<int> op; //操作符   + 1  - -1  ( 2  
        for(index ; index < s.size(); index++)
        {
            if(s[index] == '+')
            {
                op.push_back(1);
            }
            else if(s[index] == '-')
            {
                op.push_back(-1);
            }
            else if(s[index] >= '0' && s[index] <= '9')//数字
            {
                int value = parseInt(s,index);
                num.push_back(value);//
                if(num.size() >= 2 && op[op.size()-1] != 0)
                {
                    int b = num[num.size()-1];
                    num.pop_back();
                    int a = num[num.size()-1];
                    num.pop_back();
                    int c = op[op.size()-1];
                    op.pop_back();
                    num.push_back(a+b*c);
                    //calc(num, op);
                }
            }
            else if(s[index] == '(')//左括号压栈
            {
                op.push_back(0);
            }
            else if(s[index] == ')')//右括号,一直算啊算,知道算到左括号位置
            {
                while(op[op.size()-1] != 0)
                {
                    int b = num[num.size()-1];
                    num.pop_back();
                    int a = num[num.size()-1];
                    num.pop_back();
                    int c = op[op.size()-1];
                    op.pop_back();
                    num.push_back(a+b*c);  
                    //calc(num, op);
                }
                op.pop_back();
                if(num.size() >= 2 && op[op.size()-1] != 0)
                {
                    int b = num[num.size()-1];
                    num.pop_back();
                    int a = num[num.size()-1];
                    num.pop_back();
                    int c = op[op.size()-1];
                    op.pop_back();
                    num.push_back(a+b*c);
                    //calc(num, op);
                }
            }
        }
        while(num.size() != 1)
        {
            int b = num[num.size()-1];
            num.pop_back();
            int a = num[num.size()-1];
            num.pop_back();
            int c = op[op.size()-1];
            op.pop_back();
            num.push_back(a+b*c);
            //calc(num, op);
        }
        return num[0];
    }
private:
    //连读一个数
    int parseInt(string &s, int &index)
    {
        int res = 0;
        while(s[index] >= '0' && s[index] <= '9')
        {
            res*= 10;
            res+= (s[index] - '0');
            index++;
        }
        index--;
        return res;
    }
};

还有个坑一点的地方。就是解析数字这个我弄成了一个函数,最开始传参传的是string,每次传参相当于复制,所以遇到一个特别长的测试用例时候就特别慢,超时了。改成引用传参就跑过去了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 第5章 引用类型(返回首页) 本章内容 使用对象 创建并操作数组 理解基本的JavaScript类型 使用基本类型...
    大学一百阅读 3,272评论 0 4
  • 前言 把《C++ Primer》[https://book.douban.com/subject/25708312...
    尤汐Yogy阅读 9,541评论 1 51
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,779评论 18 399
  • 防晒,隔离,妆前乳, 遮瑕,粉底,再修容, 高光,腮红,与鼻影, 修眉,眉粉,眼线笔, 唇膏,口红,假睫毛 ………...
    林一茶阅读 178评论 0 0
  • 《杰出公民》很好,可惜不知道为什么我从没听说过。 不是基于我的自负,一般涉及文人传记类的电影我都很爱看。像是电影《...
    岗鉴阅读 458评论 1 5