根据逆波兰表示法,求表达式的值。
有效的运算符包括 +, -, , / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。 说明: 整数除法只保留整数部分。 给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
示例 1:
输入:
[“2”, “1”, “+”, “3”, ""]
输出: 9
解释: 该算式转化为常见的中缀算术表达式为:
((2 + 1) * 3) =9
示例 2:
输入: [“4”, “13”, “5”, “/”, “+”]
输出: 6
解释: 该算式转化为常见的中缀算术表达式为:
(4+ (13 / 5)) = 6
示例 3:
输入: [“10”, “6”, “9”, “3”, “+”, “-11”, “", “/”, "”, “17”, “+”, “5”, “+”]
输出: 22
解释: 该算式转化为常见的中缀算术表达式为:
((10 * (6 /((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22
逆波兰表达式: 逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。 平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。 该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。
逆波兰表达式主要有以下两个优点: 去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中。
题给函数:
int evalRPN(char ** tokens, int tokensSize){
}
题解:
一、首先该题很明确的给出了解题大方向:用栈处理逆波兰表达式
用栈求后缀表达式的值的方法:
将给出的后缀表达式字符串向后遍历,遇到数字则压入栈,
遇到运算符则将栈顶的数和栈顶下面那个数提出来,
用“栈顶下面那个数”“运算符”“栈顶的数”的形式求出来值后放入栈顶下面那个位置。
如stack[top]=3,stack[top-1]=5,此时扫描到的字符为'-',则a=stack[top-1],b=stack[top],stack[top-1]=a-b=2。
二、这个题需要注意的地方
(这个题给出的样例挺不错,循序渐进地给出了要注意的地方)
1、该题给出的函数为
int evalRPN(char ** tokens, int tokensSize){ }
这个 char ** tokens 是一个二维数组的首地址。
2、因为给出的是二维指针,结合样例我们可以看出每次的输入是一个字符串而不是一个字符。
如示例 3:
输入: [“10”, “6”, “9”, “3”, “+”, “-11”, “", “/”, "”, “17”, “+”, “5”, “+”]
每个双引号内都是一维。
3、测试数据中不止输入一位数,也会输入多位数,对于输入的每个字符串,要走完整个字符串才能开始下一个。
4、输入数据中会存在负数,对于该类数据要在把数字部分提出来后还要变成负数才能存入。
5、这个我被恶心到了,先把原理放在这里
signed char 类型的范围为 -128~127
unsigned char 的范围为 0~ 255
看到输入的数据都是一些字符型后,我自然而然将栈的数组类型开成了char型,结果自己测试每次循环后的结果时发现原本应为196的数字变为了-60,这才想起来char的数据范围。
解决方法是改成了int数组。
执行用时8ms
提交执行用时超过了94%的C提交记录
内存消耗7.2MB
提交消耗内存超过了79%的C提交记录
然后就是我的AC代码
int evalRPN(char ** tokens, int tokensSize){
int stack[10000];
int size,top;
int a,b,i,flag;
for(size=0,top=-1;size<tokensSize;size++)
{
if(strlen(tokens[size])==1)//只有符号或一位数
{
if(tokens[size][0]=='+')
{
b=stack[top];
a=stack[--top];
stack[top]=a+b;
}
else if(tokens[size][0]=='-')
{
b=stack[top];
a=stack[--top];
stack[top]=a-b;
}
else if(tokens[size][0]=='*')
{
b=stack[top];
a=stack[--top];
stack[top]=a*b;
}
else if(tokens[size][0]=='/')
{
b=stack[top];
a=stack[--top];
stack[top]=a/b;
}
else
{
stack[++top]=tokens[size][0]-'0';
}
}
else
{
if(tokens[size][0]=='-')
{
flag=1;//做个标记
i=1;//从负号后面找数字
}
else
{
flag=0;
i=0;
}
stack[++top]=0;
while(tokens[size][i]!='\0')
{
stack[top]=stack[top]*10+tokens[size][i]-'0';//字符串转数字标准操作
i++;
}
if(flag)
{
stack[top]*=(-1);//添上负号
}
}
}
return stack[top];
}