题目链接
实现思路
-
先遍历一遍
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);
}
};