2015华为实习生-机试题-火星计算器

先直接贴上题目,大家感受一下:

自定义运算符 @,#,$,&,并且优先级@>#>$>&,利用下面的计算法则,计算出一个给定的字符串表示的表达式的值,返回整型结果。

x@y = (x-1)*(y+1);
x#y = (2*x+5)*(3*y+60)
x$y = (x+1)*(2*x+3)*(y-1)*(2*y-3)
x&y = ((x+y+1)*(y-9)+(x+7)/(y-8))

输入:接受多行输入,每行可能有空格。题目保证不会出现除数为0的情况,且所有操作数都是整数。为了简单起见,表达式不含有括号。
输出:对于每一行输入,输出一个运算结果。

输入样例:
1@2
1#2
1@1@1
1#1#1
1$1$1
1&1&1
1#1@1
1@1#1
1$1&1
1&1$1
1  #   1  &       1
12 @        12
123    @   123

输出:
0
462 
-2
55881
0
186
420
315
-17
-19
-3608
143
15128

分析:
大体来看,程序主要流程为这么几步
1. 将得到的字符串进行去空格处理。
2. 将第1步得到的字符串(此为中缀形式)转换为逆波兰式(后缀式)
3. 将第2步得到的逆波兰式(RPN)进行计算,求出结果并输出。

核心算法伪代码:
1. 将中缀形式转化为后缀形式:

从左往右扫描inputString
    if 当前扫描的是操作数
        输出该操作数
    else   //当前扫描的是操作符
        while 无限循环
            if 栈为空 或 栈顶元素优先级小于该操作符
                该操作符入栈
                break
            else
                输出栈顶元素,并pop
//扫描inputString完毕
while 栈内还有元素
    输出栈顶元素,并pop

2.将后缀形式计算为结果

从左往右顺序扫描inputRPN
    if 当前扫描的是操作数
        该操作数入栈
    else  //当前扫描到的是操作符
        从栈中弹出两个操作数,参加该操作符的运算
        运算结果入栈

注意细节:
1. 在由于要处理76 @ 321 这样的多位操作数,因此在转换RPN的时候要注意顺带进行atoi的操作。
2. 若直接用cin>>进行初始化输入的操作,题目中的空格被隔断成多个字符串,比如这种输入123 @ 123 ,因此要使用getline来进行初始化操作。

成品代码:
使用C++11 mode下的GCC编译通过。

#include <iostream>
#include <map>
#include <stack>
#include <vector>

using namespace std;

class MarsCalc {
public:
    int calcResult(string inputStr) {
        string stringWithoutSpace = removeSpcace(inputStr);
        vector<int> RPN = convertToRPN(stringWithoutSpace);
        return calcRPN(RPN);
    }

private:
    map<char, int> queryPriority = map<char, int> { { '@', INT32_MIN + 1 }, { '#', INT32_MIN + 2 }, { '$', INT32_MIN + 3 }, { '&', INT32_MIN + 4 } };

    string removeSpcace(string inputStr) {
        string stringWithoutSpace;
        for (char ch : inputStr)
            if (ch != ' ')
                stringWithoutSpace.append(1, ch);
        return stringWithoutSpace;
    }

    vector<int> convertToRPN(string inputStr) {
        vector<int> RPN2;
        stack<char> operatorStack;
        int atoiNumber = 0;
        for (char ch : inputStr) {
            if (ch >= '0' && ch <= '9') {       //操作数
                atoiNumber = atoiNumber * 10 + ch - '0';
            } else {        //操作符
                RPN2.push_back(atoiNumber);
                atoiNumber = 0;     //atoi清零
                while (true) {
                    if (operatorStack.empty() == true || queryPriority[operatorStack.top()] > queryPriority[ch]) {
                        operatorStack.push(ch);
                        break;
                    } else {
                        RPN2.push_back(queryPriority[operatorStack.top()]);
                        operatorStack.pop();
                    }
                }
            }
        }
        RPN2.push_back(atoiNumber);
        while (operatorStack.empty() == false) {        //弹出栈内操作符
            RPN2.push_back(queryPriority[operatorStack.top()]);
            operatorStack.pop();
        }
        return RPN2;
    }

    int calcRPN(vector<int> inputRPN) {
        stack<int> numberStack;
        for (auto& it : inputRPN) {
            if (it > INT32_MIN + 4) {       //操作数
                numberStack.push(it);
            } else {
                int num1 = numberStack.top();
                numberStack.pop();
                int num2 = numberStack.top();
                numberStack.pop();
                numberStack.push(doMarsCalc(num2, num1, it));
            }
        }
        return numberStack.top();
    }

    int doMarsCalc(int num1, int num2, int operate) {
        switch (operate) {
        case INT32_MIN + 1:     //'@':
            return (num1 - 1) * (num2 + 1);
        case INT32_MIN + 2:         //'#':
            return (2 * num1 + 5) * (3 * num2 + 60);
        case INT32_MIN + 3:         //'$':
            return (num1 + 1) * (2 * num1 + 3) * (num2 - 1) * (2 * num2 - 3);
        case INT32_MIN + 4:         //'&':
            return ((num1 + num2 + 1) * (num2 - 9) + (num1 + 7) / (num2 - 8));
        }
    }
};

int main() {
    MarsCalc marsCalc;
    string inputStr;
    while (getline(cin, inputStr)) {
        cout << marsCalc.calcResult(inputStr) << endl;
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值