携手创作,共同成长!这是我参与「掘金日新计划 · 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开始,挨个和前面计算的结果进行计算(这里可将计算结果初始化为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;
}
};