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


    题目描述

    给定一个表示分数加减运算的字符串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;

    1. static class Dot {
    2. int up;
    3. int down;
    4. }

    分数做化简

    这里直接从2到分母值循环,如果循环完成没有公约数则返回,如果有公约数则进行一次化简后递归调用本方法,代码实现如下:

    1. private Dot rebuild(Dot res) {
    2. for (int i = 2; i <= res.down; i++) {
    3. if (res.up % i == 0 && res.down % i == 0) {
    4. Dot dot = new Dot();
    5. dot.up = res.up / i;
    6. dot.down = res.down / i;
    7. return rebuild(dot);
    8. }
    9. }
    10. return res;
    11. }

    分数的加法

    判断两个分数分母是否相同,如果相同直接用分子相加;如果不同则需要把分母变成一样后做加法;代码参考:

    1. Dot add(Dot left, Dot right) {
    2. Dot res = new Dot();
    3. if (left.down == right.down) {
    4. res.up = left.up + right.up;
    5. res.down = left.down;
    6. } else {
    7. res.up = left.up * right.down + right.up * left.down;
    8. res.down = left.down * right.down;
    9. }
    10. return rebuild(res);
    11. }

    代码实现

    1. class Solution {
    2. public String fractionAddition(String expression) {
    3. Dot last = null;
    4. int length = expression.length();
    5. for (int i = 0; i < length; ) {
    6. if (expression.charAt(i) == '+' || expression.charAt(i) == '-' || i == 0) {
    7. Dot dot = new Dot();
    8. int v = 1;
    9. if (expression.charAt(i) == '+' || expression.charAt(i) == '-') {
    10. if (expression.charAt(i) == '-') {
    11. v = -1;
    12. }
    13. i++;
    14. }
    15. int start = i;
    16. while (i < length && expression.charAt(i) >= '0' && expression.charAt(i) <= '9') {
    17. i++;
    18. }
    19. dot.up = v * Integer.valueOf(expression.substring(start, i));
    20. if (i < length && expression.charAt(i) == '/') {
    21. i++;
    22. } else {
    23. throw new RuntimeException("操作符异常");
    24. }
    25. start = i;
    26. while (i < length && expression.charAt(i) >= '0' && expression.charAt(i) <= '9') {
    27. i++;
    28. }
    29. dot.down = Integer.valueOf(expression.substring(start, i));
    30. if (last == null) {
    31. last = dot;
    32. } else {
    33. last = add(last, dot);
    34. }
    35. }
    36. }
    37. return last.up + "/" + last.down;
    38. }
    39. Dot add(Dot left, Dot right) {
    40. Dot res = new Dot();
    41. if (left.down == right.down) {
    42. res.up = left.up + right.up;
    43. res.down = left.down;
    44. } else {
    45. res.up = left.up * right.down + right.up * left.down;
    46. res.down = left.down * right.down;
    47. }
    48. return rebuild(res);
    49. }
    50. private Dot rebuild(Dot res) {
    51. for (int i = 2; i <= res.down; i++) {
    52. if (res.up % i == 0 && res.down % i == 0) {
    53. Dot dot = new Dot();
    54. dot.up = res.up / i;
    55. dot.down = res.down / i;
    56. return rebuild(dot);
    57. }
    58. }
    59. return res;
    60. }
    61. static class Dot {
    62. int up;
    63. int down;
    64. }
    65. public static void main(String[] args) {
    66. Solution solution = new Solution();
    67. System.out.println(solution.fractionAddition("-1/2+1/2"));;
    68. }
    69. }

    总结

    这是一道使用计算机模拟数学计算题,整个代码中字符转换成分数有一定复杂度,分数化简有一定复杂度,感觉是2道简单操作合并到一起就成一道中等题目了。

  • 相关阅读:
    Go :测试编译器诊断函数缺少返回语句(附完整源码)
    节能灯与led灯哪个对眼睛好?分享专业护眼的led灯
    ML之shap:分析基于shap库生成的力图、鸟瞰图、散点图等可视化图的坐标与内容详解之详细攻略
    一个复制也能玩出花来
    查找和排序算法
    Docker创建redis容器
    【Linux】gcc/g++ && gdb 使用
    积雪草酸肌白蛋白纳米粒|野黄芩苷豆清白蛋白纳米粒|黄芩苷蓖麻蛋白纳米粒(齐岳)
    车内信息安全技术-安全技术栈-软件安全
    Oracle内存结构
  • 原文地址:https://blog.csdn.net/weiliuhong1/article/details/126024865