zoukankan      html  css  js  c++  java
  • 数据结构问题集锦

    问题地址:https://leetcode.com/problems/basic-calculator/

    问题简述:给定一个含有空格、加减运算符、括号与数字的算式,对其求值。

    问题分析:站在一个熟悉数据结构的人,或者是竞赛党和大牛的角度来看,当然可以利用栈和简单的运算符优先级把表达式转化为后缀表达式,然后再利用另一个栈对转化好的表达式进行求值。然而,笔者本人是算法渣。然而对于算法渣就没有什么简单直观的方法吗?其实是有的,且听我娓娓道来。

    解法思路:分析这个Basic Calculator可知,首先应该去除空格。然后,由于只存在加减两种操作,故不需要考虑运算符优先级,从而可以顺序求值。这里顺序求值指的是,把单个的数或者括号连同其前面的符号视作一个整体进行求值,比如3+5-(2-1)当中,就可以认为分别存在+3,+5,-(2-1)三个需要进行求值的部分。对于单个数求值过程显然是简单的,对于符号后是一个括号的情况,就取出括号内部的表达式递归求值。为了识别括号内的表达式,需要一个辅助栈,每当检测到左括号就执行入栈,识别到右括号就出栈,如果空栈时检测到右括号,说明括号内的子表达式结束了。在下面的代码中,栈被简化为了一个初始化为0的计数器,入栈等价于加1而出栈等价于减1。

    运行效果:在自己简单的用例下,运行结果都十分完美。不过在LeetCode上,对于超长表达式,求值就会超时,间接证明了这个直观方法复杂度不容乐观的事实。但是,谢天谢地,程序没有出现过运行错误的情况。

    复杂度分析:设字符串的长度为m,首先去除空格的操作复杂度为O(m)。然后求值部分的复杂度,个人感觉是难于计算的,因为括号的位置、括号中间子表达式的长度等都不确定,加之程序递归执行,目前为止感觉难以分析(也许是可以的,只不过我太渣了)。

    最后附上代码吧:

     1 #include <iostream>
     2 #include <string>
     3 using namespace std;
     4 
     5 //Calculate program
     6 int calc(string exp)
     7 {
     8     exp = "+" + exp;
     9     unsigned int i = 0;
    10     int result = 0;
    11 
    12     while (i<exp.size())
    13     {
    14         bool oper = (exp[i] == '+');
    15         int num = 0;
    16         i++;
    17 
    18         //Number
    19         if (exp[i] != '(')
    20         {
    21             while ((exp[i] >= '0') && (exp[i] <= '9') && (i<exp.size()))
    22             {
    23                 num = num * 10 + (exp[i] - '0');
    24                 i++;
    25             }
    26         }
    27         //"(", recursively calculate sub-expression
    28         else
    29         {
    30             string sub_exp;
    31             unsigned int se_level = 0;
    32 
    33             i++;
    34             while (true)
    35             {
    36                 //"("
    37                 if (exp[i] == '(')
    38                     se_level++;
    39                 //")"
    40                 else if (exp[i] == ')')
    41                 {
    42                     if (se_level == 0)
    43                         break;
    44                     else
    45                         se_level--;
    46                 }
    47 
    48                 sub_exp += exp[i];
    49                 i++;
    50             }
    51             num = calc(sub_exp);
    52             i++;
    53         }
    54 
    55         result = oper ? (result + num) : (result - num);
    56     }
    57 
    58     return result;
    59 }
    60 
    61 //Main program
    62 int main()
    63 {
    64     string _exp, exp;
    65     unsigned int i;
    66 
    67     //Trim spaces
    68     getline(cin, _exp);
    69     for (i = 0; i<_exp.size(); i++)
    70         if (_exp[i] != ' ')
    71             exp += _exp[i];
    72     //Calculate expression
    73     cout << calc(exp) << endl;
    74     return 0;
    75 }

     (看完大牛们的博客之后,感觉到了自己实力的捉急。哎,还是老老实实做个工程党吧)

  • 相关阅读:
    .NET数据库编程求索之路11.一些思考
    VMware Workstation安装使用手记
    VS2010无法保存项目文件(.csprj)的问题解决方法
    【转】VC++/MFC(VC6)开发技术精品学习资料下载汇总 (2011.3.10更新)
    .NET数据库编程求索之路9.使用EF实现
    oracle11g新特性:闪回数据归档(Flashback Data Archive)#ocp试验#
    ORACLE口令文件验证与操作系统验证|转|
    闪回flashback#ocp试验#
    expdp数据泵导出操作
    手动模式下热备份的不完全恢复#OCP试验#
  • 原文地址:https://www.cnblogs.com/lqf-96/p/basic-calculator.html
Copyright © 2011-2022 走看看