每日LeetCode —— 592. 分数加减运算

230 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第1天,点击查看活动详情

题目描述

给定一个分数加减运算的字符串,返回字符串形式的计算结果;

例1:输入:"2/3+1/2"  输出:"7/6"

例2:输入:"3/6-1/2"  输出:"0/1"

本题值得注意的地方

  • 需要对计算出的结果进行约分
  • 若第一个分数为正,该分数前不会有字符 '+', 如例二中的输入不会为"+3/6-1/2"。
  • 若计算的结果为 0,则应输出 "0/1" 而不是 "0/2"。

原题地址:592. 分数加减运算

解题思路

       因为题目中分数的正负由分子决定的,所以可以利用分子的符号将分数字符串分割开来,利用正负号来判断当前分数的开始与结束。

1.png

       从分数1开始,挨个和前面计算的结果进行计算(这里可将计算结果初始化为0),计算结果的分子分母分别保存到两个变量中去(初始化分子为0,分母为1),每相加一个分数,需要将当前的结果值更新。

       这里相加时需要求出前面结果的分母与当前分数分母的最小公倍数,然后进行约分计算。

       计算完成后,将结果的分子分母进行约分得到分数的最简形式,并根据正负以及结果是否为0进行不同情况的答案拼接并返回。

实现代码

class Solution {
public:
    // 求两个数的最大公约数
    long long gcd(long long a,long long b){
        if(b != 0) return gcd(b,a%b);
        else return a;
    }
    string fractionAddition(string exp) {
        // 若第一个分数为正,则在其前加上+号,统一运算。
        if(isdigit(exp[0])) exp = '+'+exp;
        int n = exp.size();
        // 保存结果的分子与分母,初始化为 0
        long long mo = 0,de = 1;
        for(int i = 0;i < n;){
            int curMo = 0,curDe = 0;
            // 记录当前分数的正负情况
            char c=exp[i++];
            // 计算当前分数的分子
            while(i<n && isdigit(exp[i])) curMo = curMo*10 + (long long)(exp[i++]-'0');
            // 跳过 '/' 号
            i++;
            // 计算当前分数的分母
            while(i<n && isdigit(exp[i])) curDe = curDe*10 + (exp[i++] - '0');  
            // 回复当前分数的正负号
            if(c=='-') curMo *= -1;
            // 计算当前分数的分母与前面计算的结果的分母的最小公倍数,该最小公倍数即为新结果的分母
            long long lcm = de * curDe/gcd(de,curDe);
            // 相加分子
            mo = mo*(lcm/de) + curMo*(lcm/curDe);
            de = lcm;
        }
        // 此时 mo 、 de 即为没有进行约分的结果
        string res = "";
        if(mo<0) res += '-',mo *= -1;
        // 计算分子分母的最大公约数
        int curgcd = gcd(mo,de);
        // 分数进行约分
        mo /= curgcd;
        // 若当前计算的结果为 0 即分子为 0 ,则将分母置 1
        de = mo==0?1:de/curgcd;
        // 进行结果的拼接并返回
        res += to_string(mo) + "/" + to_string(de);
        return res; 
    }
};