【LeetCode-中等】592. 分数加减运算(C++实现)

题目链接

592. 分数加减运算

实现思路

  • 先遍历一遍 expression,把数值先暂存。

    遍历过程中,遇到 +-,都将前面的字符串转换为 int 存在 Node 中。

    默认情况下,如果 pre == -1,说明正在遍历第一个分数,此时将其设为 0。

  • str2int():将前面的字符串转换为 int 存在 Node 中。

    字符串按照 ‘/’ 分割即可。

  • calAndSprint():计算,格式化字符串。

    遍历 vals 数组。每一步的计算分为4个部分:计算最小公倍数、通分、计算、约分。

    符号判断由 fz * fm 来判定,之后返回结果即可。

实现代码(C++)

struct Node {
    int fz, fm;
    bool isAct; // 是否为正
};
class Solution {
public:
    Node str2int(string str, bool isAct) {
        int pos = str.find("/", 0);
        string fzStr = str.substr(0, pos);
        string fmStr = str.substr(pos+1, str.length() - pos - 1);

        stringstream ss1, ss2;
        ss1 << fzStr;
        int fz = 0;
        ss1 >> fz;
        ss2 << fmStr;
        int fm = 0;
        ss2 >> fm;

        Node node;
        node.fz = fz;
        node.fm = fm;
        node.isAct = isAct;
        
        return node;
    }
    string calAndSprint(vector<Node> &vals) {
        int fz = 0, fm = 1;
        for (int i = 0; i < vals.size(); i++) {
            // 1. 计算最小公倍数
            int minN = __gcd(fm, vals[i].fm);
            int newFm = fm * vals[i].fm / minN;
            // 2. 通分
            int newFzi = (newFm / vals[i].fm) * vals[i].fz;
            int newFzAns = (newFm / fm) * fz;
            // 3. 计算
            if (vals[i].isAct) { // +
                fz = newFzAns + newFzi;
            } else { // -
                fz = newFzAns - newFzi;
            }
            fm = newFm;
            // 4. 约分
            minN = __gcd(fm, fz);
            fm /= minN;
            fz /= minN;
        }
        string ans;
        if (fz * fm < 0) {
            ans += '-';
        }
        return ans + to_string(abs(fz)) + "/" + to_string(abs(fm));
    }
    string fractionAddition(string expression) {
        vector<Node> vals;
        int len = expression.length();
        bool isAct = true;
        int pre = -1;
        for (int i = 0; i < len; i++) {
            switch (expression[i]) {
                case '-':
                    if (pre == -1) {
                        pre = 0;
                    }
                    vals.push_back(str2int(expression.substr(pre, i - pre), isAct));
                    isAct = false;
                    pre = i + 1;
                    break;
                case '+':
                    if (pre == -1) {
                        pre = 0;
                    }
                    vals.push_back(str2int(expression.substr(pre, i - pre), isAct));
                    isAct = true;
                    pre = i + 1;
                    break;
                default:
                    if (pre == -1) {
                        pre = 0;
                    }
            }
        }
        // 最后一个分数
        string tmpNum = expression.substr(pre, len - pre);
        vals.push_back(str2int(tmpNum, isAct));
        if (vals[0].fm == 0) { // 在第一个的字符为正、符号的情况下,会多出一个"+0/0",将它的分母设为1即可,不影响结果
            vals[0].fm = 1;
        }

        // 计算结果
        return calAndSprint(vals);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值