数据结构问题集锦

问题地址: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 }

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

原文地址:https://www.cnblogs.com/lqf-96/p/basic-calculator.html