【问题标题】:Efficiently parse single digit arithmetic expression高效解析个位数算术表达式
【发布时间】:2013-09-12 04:45:42
【问题描述】:

您将如何在 Java 中有效地(优化运行时同时保持空间最小化)解析和评估单个数字算术表达式。

下列算术表达式均有效:

eval("-5")=-5
eval("+4")=4
eval("4")=4
eval("-7+2-3")=-8
eval("5+7")=12

我的方法是遍历所有元素,使用标志跟踪当前算术运算,并逐位计算。

public int eval(String s){
    int result = 0;
    boolean add = true; 
    for(int i = 0; i < s.length(); i++){
        char current = s.charAt(i);
        if(current == '+'){
            add = true;
        } else if(current == '-'){
            add = false;
        } else {
            if(add){
                result +=  Character.getNumericValue(current);
            } else {
                result -= Character.getNumericValue(current);
            }
        }
    }
    return result;
} 

这是唯一的最佳解决方案吗?我曾尝试使用堆栈来跟踪算术运算符,但我不确定这是否更有效。我也没有尝试过正则表达式。我之所以问,是因为我在一次采访中给出了上述解决方案,并被告知这是次优的。

【问题讨论】:

  • 你有没有这样的案例:eval("4+-5")?
  • @KrishnaSarma 是的,考虑到属性(例如 eval("+5")=5 或 eval("-4")=-4)
  • new ScriptEngineManager().getEngineByExtension("js").eval("-7+4") 只是因为我非常懒惰。
  • 您可以使用向量、数组列表或堆栈类来进一步优化您的代码,而不是使用字符串。一般来说,我们不经常使用字符串,因为它们往往会占用更多资源。
  • @NiteshVerma 这就是我无法理解的。我正在做的唯一字符串操作似乎是完全必要的,因为您必须从字符串中解析每个操作和数字。

标签: java algorithm parsing


【解决方案1】:

这似乎更紧凑一些。它当然需要更少的行和条件。关键是添加是“默认”行为,您遇到的每个减号都会更改您要添加的符号;前提是您记得在每次添加后重置符号。

public static int eval(String s){
    int result = 0;
    int sign = 1; 
    for(int i = 0; i < s.length(); i++){
        char current = s.charAt(i);
        switch (current)
        {
            case '+': break;
            case '-': sign *= -1; break;
            default: 
                result += sign * Character.getNumericValue(current);
                sign = 1;
                break;
        }
    }
    return result;
}

作为说明,我认为您的添加否定结果不会产生正确的结果,例如“4- -3”。您的代码生成 1,而不是正确的值 7。另一方面,我的代码允许诸如“5+-+-3”之类的表达式,这将产生结果 8(我想这是正确的?:)。但是,您没有将验证列为一项要求,并且我们都没有检查连续数字、字母字符、空格等。如果我们假设数据格式正确,则上述实现应该可以工作。我看不出在这里添加数据结构(例如队列)有什么帮助。我也假设只是加法和减法。

这些测试用例产生以下结果:

System.out.println(eval("1+2+3+4"));
System.out.println(eval("1--3"));
System.out.println(eval("1+-3-2+4+-3"));

10
4
-3

【讨论】:

  • 我刚试过这个,我找不到让该功能无法正常工作的方法。我首先会做一个正则表达式检查,以确保参数不包含空格或任何不同的东西,而不是数字或符号
  • 这只有在没有运算符优先级或括号时才有效。
  • 我已经提到我只假设加法和减法,在这种情况下优先级无关紧要;你从左到右评估。除了加法和减法之外,没有一个例子包括任何东西。鉴于输入限制为单个数字,我假设他们不想要涉及正则表达式的解决方案,必须对其进行解析并通常为输入构建后缀树。这需要一次(相对较快)通过字符串。这显然不是评估一般算术表达式的“正确”方法:不是问题!
  • @Jeremy West:谁说正则表达式需要后缀树?他们没有。正确编译的正则表达式是一个简单的有限状态自动机,它在 O(n) 中解析输入,其中 n 是输入字符串的长度。不要让您被流行的正则表达式引擎误导,它们在最坏的情况下具有指数(!)复杂性。
  • 您可以提及任何您喜欢的内容,但除非您提及的约束条件在 OP 的问题中明确显示,否则这不是一个可以接受的答案。
【解决方案2】:

您需要查找“递归下降表达式解析器”或 Dijkstra 分流场算法。当您必须处理运算符优先级或括号时,您目前的方法注定要失败。您还需要忘记正则表达式并辞职去编写合适的扫描器。

【讨论】:

  • 你读过这个问题吗?在一次采访中被问到,大概他们想要代码,并且仅限于单个数字的值。我不认为他们在寻找功能齐全的解析器。
  • 不清楚您是否理解这里的问题。 “一个数字的值”与它无关。他需要一个表达式解析器,除非有其他约束,不提。这是我要给出的答案,如果他们告诉我那是“次优的”,我会走路,在编译器中实现了几十次。相反,如果我是面试官,(a)我不会问这样的问题,因为我已经准备好培训具有合适能力的候选人,但是(b)任何人都可以提供答案如果没有某种堆栈,就会显示门。
  • 不,我绝对理解这里的问题。
猜你喜欢
  • 2013-12-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-17
  • 1970-01-01
  • 2022-09-26
  • 2011-01-25
  • 2015-12-20
相关资源
最近更新 更多