首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >计算一个完全带括号的算术表达式

计算一个完全带括号的算术表达式
EN

Code Review用户
提问于 2016-07-22 17:03:31
回答 1查看 3.9K关注 0票数 5

我试图在编程挑战中解决以下问题,但结果超过了时间限制。

完全带括号的表达式编写一个程序,该程序读取一个完全带括号的表达式,并打印计算结果。这三种可能的运算符是和、减和乘。操作数是0到9之间的自然数(都包括在内)。输入输入有一个完全带括号的表达式。也就是说,括号总是出现在不是数字的子表达式的周围。例如,表达式4 + 3将写入( 4 + 3 )表达式8 * (4 + 3)将写入( 8 * ( 4 + 3 ) )表达式(2 − 8) * (4 + 3)将写入((2-8)*(4+3))输出用整数打印一行:计算给定表达式的结果。(资料来源:https://jutge.org/problems/P45102_en/陈述)

一些公共测试用例是(每一行都是不同的测试用例):

代码语言:javascript
复制
9
( 3 + 4 )
( 8 * ( 4 + 3 ) )
( ( 2 - 8 ) * ( 4 + 3 ) )
( ( 3 * 2 ) + 1 )

这是我的代码,它通过了每个公共测试用例,但不是私有测试用例。为了找出我节目的瓶颈,我请求你的帮助。

代码语言:javascript
复制
#include <iostream>
#include <sstream>

using std::string;
using std::cin;
using std::cout;

/**
 * Returns the evaluation of a completely parenthesed expression.
 * 
 * Preconditions:
 *     * 0 <= i <= j < expr.size()-1.
 *     * expr is a completely parenthesed expression.
 * 
 * Postcondition: returns the evaluation of expr[i..j].
 */

int evaluate(const string& expr, int i, int j)
{
    // Skip leading blanks
    while (expr[i] == ' ') {
        ++i;
    }
    while (expr[j] == ' ') {
        --j;
    }

    // Base case
    if (i == j) {
        return expr[i] - '0';
    }
    // Recursive case
    else {
        // Skip first and last parentheses
        ++i;
        --j;
        int open_parentheses = 0;
        int end_i = i;
        // Loop invariant:
        //     * expr[i..end_i) is part of the first subexpression of expr[i..j]
        //     * open_parentheses is the balance of opened and closed parentheses of expr[i..end_i)
        while (open_parentheses > 0 || (expr[end_i] != '+' && expr[end_i] != '-' && expr[end_i] != '*')) {
            if (expr[end_i] == '(') {
                ++open_parentheses;
            }
            else if (expr[end_i] == ')') {
                --open_parentheses;
            }
            ++end_i;
        }
        // Loop ending: expr[end_i] is the 'main' operation of expr[i..j]

        char operation = expr[end_i];

        // By induction hypothesis,
        //     evaluate(expr, i, end_i - 1) 
        // and
        //     evaluate(expr, end_i + 1, j)
        // return the values of the first and the second subexpression of expr[i..j]

        if (operation == '+') {
            return evaluate(expr, i, end_i - 1) + evaluate(expr, end_i + 1, j);
        } else if (operation == '-') {
            return evaluate(expr, i, end_i - 1) - evaluate(expr, end_i + 1, j);
        } else {
            int first_expression = evaluate(expr, i, end_i - 1);
            // Multiplication shortcut
            if (first_expression == 0) {
                return 0;
            } else {
                return first_expression * evaluate(expr, end_i + 1, j);   
            }
        }
    }
}

int main()
{
    string expr;
    getline(cin, expr);
    cout << evaluate(expr, 0, expr.size() - 1) << "\n";
}
EN

回答 1

Code Review用户

回答已采纳

发布于 2016-07-24 14:53:09

我得到了以下代码的通过率。

一些评论:

  • ints搬到了string::const_iterators,效率低下。
  • 没有搬到isspace。我相信,如果效率不是那么重要,但在效率方面却失败了,那将是一个更好的选择。
  • 我简化了递归决策块。

守则:

代码语言:javascript
复制
#include <iostream>
#include <sstream>

using std::string;
using std::cin;
using std::cout;

typedef string::const_iterator it;


/**
 * Returns the evaluation of a completely parenthesed expression.
 * 
 * Preconditions:
 *     * i and j point to characters of expr.
 *     * expr is a completely parenthesed expression.
 * 
 * Postcondition: returns the evaluation of expr[i..j].
 */
int evaluate(const string& expr, it i, it j)
{
    // Skip leading blanks
    while (*i == ' ') {
        ++i;
    }
    while (*j == ' ') {
        --j;
    }

    // Base case
    if (i == j) {
        return *i - '0';
    }

    // Recursive case
    // Skip first and last parentheses
    ++i;
    --j;
    int open_parentheses = 0;
    it end_i = i;
    // Loop invariant:
    //     * expr[i..end_i) is part of the first subexpression of expr[i..j]
    //     * open_parentheses is the balance of opened and closed parentheses of expr[i..end_i)
    while (open_parentheses > 0 || (*end_i != '+' && *end_i != '-' && *end_i != '*')) {
        if (*end_i == '(') {
            ++open_parentheses;
        }
        else if (*end_i == ')') {
            --open_parentheses;
        }
        ++end_i;
    }
    // Loop ending: *end_i is the 'main' operation of expr[i..j]

    char operation = *end_i;

    it begin_j = end_i;
    ++begin_j;
    --end_i;
    int first = evaluate(expr, i, end_i);
    if (operation == '*') {
        if (first == 0) {
            return 0;
        } else {
            int second = evaluate(expr, begin_j, j);
            return first * second;   
        }
    } else {
        int second = evaluate(expr, begin_j, j);
        if (operation == '+') {
            return first + second;
        } else {
            return first - second;
        }
    }
}


int main()
{
    string expr;
    getline(cin, expr);
    it i, j;
    i = expr.begin();
    j = expr.end();
    --j;
    cout << evaluate(expr, i, j) << "\n";
}
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/135615

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档