题解 | #表达式求值#

表达式求值

https://www.nowcoder.com/practice/9566499a2e1546c0a257e885dfdbf30d

这道题,其实和leetCode.394差不太多,要稍微难一点。
我们主要要知道有哪几种情况:1.数字 2.括号 3.运算符。总的来说其实就是这三种
先说说数字,简单举个例子:30+2
首先,我们要考虑到出现非个位数的情况,将其进行组装。
接着我们要知道运算符是什么,当前是+号,那么说明我们之前收集到的数字是可以和后面的数之前累加的,所以我们先将其放入栈中。
接着遍历到2这个字符,我们还是会设置一个变量去赋值。但此时我们要考虑到一点,就是它已经处于最后一位了。咱们需要进行计算了,需要将其放入栈中了。所以这里我们需要判断当前的下标是否是处于最后一位(i==length-1)

再来看看括号我们怎么处理,大家其实都知道,如果在表达式中出现括号,那么肯定是需要先进行计算的。所以呢,需要将括号中的表达式提取出来进行计算,然后返回结果。
比如:2*(3+2)+(5-1)
我们首先需要定位括号的范围,也就是下标的范围是多少。所以咱们需要定位"("和")"。所以遇到"("就加1,")"就减1.如果等于0了,说明其中一个括号表达式中的范围我们找到了。

最后来看看运算符,加减乘除。
比如说:50-2
之前咱们说过了,会考虑非个位数的数字。首先我们已经将50这个数字组装好了,然后接着遍历到"-"减号这个位置。但是这里我们要考虑一个问题,就是需要把之前收集的数字先放到栈中去。所以呢,我们默认设置符号是加号,如果是加号,那么直接将数字放入栈中。放好之后,我们要考虑怎么让50和2进行减法运算。所以在放入栈中之后,我们需要将符号进行替换,此时从+变成了- 。 OK,接着遍历,这个时候已经遍历到2这个字符了。此时已经是最后一位了,我们需要运算。所以需要将2也放入栈中,由于此时符号已经被替换为了减号。所以我们将 2*-1 的结果放入栈中。
乘除也是一样的,因为乘除的优先级比加减要高。所以我们将之前放入栈中的前一个数字出栈,与当前的数字直接进行乘/除运算。将结果在丢入栈中即可

我们得到栈的结果之后,让其进行出栈。然后运算(这里建议默认使用加法运算)

import java.util.*;

// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        // 注意 hasNext 和 hasNextLine 的区别
        System.out.println(getVal(in.nextLine()));
    }

    private static int getVal(String str) {
        // 计算题 3+2-5
        // 1.数字处理  2.括号处理  3.+-*/处理
        // 存放数字
        Stack<Integer> stack = new Stack<>();
        int num = 0;
        // 默认是+号
        char sign = '+';
        // 注意下标越界
        char[] chars = str.toCharArray();
        int n = chars.length;
        for (int i = 0; i < chars.length; i++) {
            char cVal = chars[i];
            if (Character.isDigit(cVal)) {
                // 组装数字
                num = num * 10 + Integer.valueOf(String.valueOf(cVal));
            } else if (cVal == '(') {
                int j = i + 1;
                int count = 1;
                while (count > 0) {
                    if (chars[j] == ')') count--;
                    if (chars[j] == '(') count++;
                    j++;
                }
                // 得到括号中的数据进行处理
                num = getVal(str.substring(i + 1, j - 1));
                // 将下标修改 此时代表括号。由于下次循环会自动+1,所以不用j
                i = j - 1;
            }
            // i==n-1是为了让其进行运算。这里使用if的原因也是如此
            if (!Character.isDigit(cVal) || i == n - 1) {
                // 如果是运算符
                if (sign == '+') {
                    stack.push(num);
                } else if (sign == '-') {
                    stack.push(num * -1);
                } else if (sign == '*') {
                    stack.push(stack.pop() * num);
                } else if (sign == '/') {
                    stack.push(stack.pop() / num);
                }
                // 替换符号
                sign = cVal;
                // 将num置空
                num = 0;
            }
        }
        int ans = 0;
        while (!stack.isEmpty()) {
            ans += stack.pop();
        }
        return ans;
    }
}


#华为OD机考#
全部评论

相关推荐

牛客410815733号:这是什么电影查看图片
点赞 评论 收藏
分享
一个菜鸡罢了:哥们,感觉你的简历还是有点问题的,我提几点建议,看看能不能提供一点帮助 1. ”新余学院“别加粗,课程不清楚是否有必要写,感觉版面不如拿来写一下做过的事情,教育经历是你的弱势就尽量少写 2. “干部及社团经历”和“自我评价”删掉 3. 论文后面的“录用”和“小修”啥的都删掉,默认全录用,问了再说,反正小修毕业前肯定能发出来 4. 工作经验和研究成果没有体现你的个人贡献,着重包装一下个人贡献
点赞 评论 收藏
分享
评论
点赞
1
分享
牛客网
牛客企业服务