C语言实现力扣第150题逆波兰表达式求值

本文介绍了一种使用栈处理逆波兰表达式的方法,以计算给定的后缀表达式的值。在处理过程中,遇到数字时将其压入栈,遇到运算符则取出栈顶两个元素进行相应运算,并将结果存回栈中。需要注意输入数据的格式,例如二维字符数组,以及可能存在的负数和整数除法。示例展示了如何处理包含加减乘除及负数的复杂表达式。代码实现中,由于字符类型的限制,应使用int数组来存储计算过程中的数值,以避免溢出问题。
摘要由CSDN通过智能技术生成

根据逆波兰表示法,求表达式的值。

有效的运算符包括 +, -, , / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。 说明: 整数除法只保留整数部分。 给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 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];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值