题目描述
给定一个表示分数加减运算的字符串expression,你需要返回一个字符串形式的计算结果。并且这个结果是不可约分的分数,即最简分数。
示例1:
输入:expression = "-1/2+1/2"
输出:"0/1"
示例2:
输入:expression = "1/3-1/2"
输出:"-1/6"
约束条件:
- 输入的字符串中只包含0-9的字符,以及'/','+'和'-'
- 输入的分数个数范围是 [1,10]。
解题思路
这道题可以拆分成:
- 字符串转换成分数,并且这个分数带了符号;
- 对两个有符号的分数做加法;
- 对分数进行约分,变成最简分数;
- 将结果重新拼接成字符串并且返回。
这里重点讲一下:分数的数据结构、两个有符号的分数做加法、化简分数;
分数的数据结构
新构造一个类:Dot,分子:up,分母:down;
static class Dot {
int up;
int down;
}
分数做化简
这里直接从2到分母值循环,如果循环完成没有公约数则返回,如果有公约数则进行一次化简后递归调用本方法,代码实现如下:
private Dot rebuild(Dot res) {
for (int i = 2; i <= res.down; i++) {
if (res.up % i == 0 && res.down % i == 0) {
Dot dot = new Dot();
dot.up = res.up / i;
dot.down = res.down / i;
return rebuild(dot);
}
}
return res;
}
分数的加法
判断两个分数分母是否相同,如果相同直接用分子相加;如果不同则需要把分母变成一样后做加法;代码参考:
Dot add(Dot left, Dot right) {
Dot res = new Dot();
if (left.down == right.down) {
res.up = left.up + right.up;
res.down = left.down;
} else {
res.up = left.up * right.down + right.up * left.down;
res.down = left.down * right.down;
}
return rebuild(res);
}
代码实现
class Solution {
public String fractionAddition(String expression) {
Dot last = null;
int length = expression.length();
for (int i = 0; i < length; ) {
if (expression.charAt(i) == '+' || expression.charAt(i) == '-' || i == 0) {
Dot dot = new Dot();
int v = 1;
if (expression.charAt(i) == '+' || expression.charAt(i) == '-') {
if (expression.charAt(i) == '-') {
v = -1;
}
i++;
}
int start = i;
while (i < length && expression.charAt(i) >= '0' && expression.charAt(i) <= '9') {
i++;
}
dot.up = v * Integer.valueOf(expression.substring(start, i));
if (i < length && expression.charAt(i) == '/') {
i++;
} else {
throw new RuntimeException("操作符异常");
}
start = i;
while (i < length && expression.charAt(i) >= '0' && expression.charAt(i) <= '9') {
i++;
}
dot.down = Integer.valueOf(expression.substring(start, i));
if (last == null) {
last = dot;
} else {
last = add(last, dot);
}
}
}
return last.up + "/" + last.down;
}
Dot add(Dot left, Dot right) {
Dot res = new Dot();
if (left.down == right.down) {
res.up = left.up + right.up;
res.down = left.down;
} else {
res.up = left.up * right.down + right.up * left.down;
res.down = left.down * right.down;
}
return rebuild(res);
}
private Dot rebuild(Dot res) {
for (int i = 2; i <= res.down; i++) {
if (res.up % i == 0 && res.down % i == 0) {
Dot dot = new Dot();
dot.up = res.up / i;
dot.down = res.down / i;
return rebuild(dot);
}
}
return res;
}
static class Dot {
int up;
int down;
}
public static void main(String[] args) {
Solution solution = new Solution();
System.out.println(solution.fractionAddition("-1/2+1/2"));;
}
}
总结
这是一道使用计算机模拟数学计算题,整个代码中字符转换成分数有一定复杂度,分数化简有一定复杂度,感觉是2道简单操作合并到一起就成一道中等题目了。