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,每次传参相当于复制,所以遇到一个特别长的测试用例时候就特别慢,超时了。改成引用传参就跑过去了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,335评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,895评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,766评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,918评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,042评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,169评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,219评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,976评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,393评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,711评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,876评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,562评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,193评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,903评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,699评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,764评论 2 351

推荐阅读更多精彩内容

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