【数学】模拟分数加减运算

题目描述

给定一个表示分数加减运算的字符串expression,你需要返回一个字符串形式的计算结果。并且这个结果是不可约分的分数,即最简分数。

示例1:

输入:expression = "-1/2+1/2"

输出:"0/1"

示例2:

输入:expression = "1/3-1/2"

输出:"-1/6"

约束条件:

  • 输入的字符串中只包含0-9的字符,以及'/','+'和'-' 
  • 输入的分数个数范围是 [1,10]。

解题思路

这道题可以拆分成:

  1. 字符串转换成分数,并且这个分数带了符号;
  2. 对两个有符号的分数做加法;
  3. 对分数进行约分,变成最简分数;
  4. 将结果重新拼接成字符串并且返回。

这里重点讲一下:分数的数据结构、两个有符号的分数做加法、化简分数;


分数的数据结构

新构造一个类: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道简单操作合并到一起就成一道中等题目了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值