leetcode
leetcode 2751 ~ 2800
分式化简

分式化简

难度:

标签:

题目描述

English description is not available for the problem. Please switch to Chinese.
 

代码结果

运行时间: 22 ms, 内存: 16.0 MB


/* 
题目思路:
1. 从数组的最后一个元素开始计算。
2. 使用递归或者迭代的方法,将当前的连分数转化为一个最简分数。
3. 使用欧几里得算法求最大公约数,简化结果。
4. 使用Java Stream来简化循环的写法。
*/

import java.util.Arrays;

public class FractionConversionStream {
    public static int[] fraction(int[] cont) {
        return Arrays.stream(cont)
                .boxed()
                .reduce(new int[]{cont[cont.length - 1], 1}, (acc, cur) -> new int[]{cur * acc[0] + acc[1], acc[0]}, (a, b) -> a);
    }

    private static int gcd(int a, int b) {
        if (b == 0) return a;
        return gcd(b, a % b);
    }

    public static void main(String[] args) {
        int[] cont = {3, 2, 0, 2};
        int[] result = fraction(cont);
        int gcd = gcd(result[0], result[1]);
        System.out.println("[" + (result[0] / gcd) + ", " + (result[1] / gcd) + "]");
    }
}

解释

方法:

题解的思路是从连分数的最后一个元素开始向前处理,通过逆向计算的方式逐步构建连分数的分子和分母。具体来说,初始化分子n为0,分母m为1,然后逆序遍历输入数组的每一个元素a,每次更新分子n和分母m的值。更新规则是:将当前的分母m赋值给分子n,新的分母m计算为当前元素a乘以原分母m加上原分子n。这种逆序处理方式直接得到了最简形式的分数,因为每步计算都保证分子和分母的最大公约数为1。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么在初始化分子n为0和分母m为1时,这样的初始值可以适用于所有情况的计算?
在处理连分数时,初始值设置为分子n为0和分母m为1是为了开始逆序计算时能正确地构造分数。这种初始化相当于从一个非常简单的分数0/1开始,确保了在算法的第一步,即使连分数的最后一个元素被处理,也能正确地将其转化为有效的分数形式。此外,分子为0和分母为1的分数在数学上表示为0,这是一个合理的起点,因为任何数与0的和都是那个数本身,这保证了连分数的最后一个元素可以正确初始化整个逆序处理过程。
🦆
在逆序处理连分数时,如何确保每步更新后分子和分母的最大公约数仍然为1?
在连分数的逆序处理中,每次更新都是用当前元素a、前一步的分母m和前一步的分子n来计算新的分母。由于分子n和分母m在更新前是互质的(即最大公约数为1),并且每次更新分母为 `m * a + n`,这种更新方式相当于对两个互质的数进行线性组合。根据数论中的性质,两个互质的整数的任何线性组合也与这两个数的任何一个互质。因此,每次更新后的新分子(旧的分母m)和新分母(m * a + n)仍然是互质的。
🦆
题解中提到返回结果的顺序是分母在前,分子在后,这种顺序与常规的分数表示(分子在前,分母在后)不同,为什么要这样设计?
这种设计可能是为了强调算法输出的特别格式或者是为了适应特定的编程或数据处理需求。在数学和大多数实际应用中,分数通常表示为分子在前、分母在后。然而,在特定的上下文或系统中,可能需要按照分母在前的顺序来处理数据,以便于特定的数学操作或编程逻辑。在没有具体上下文的情况下,这种设计可能仅是为了说明或者测试输出格式的不同可能性。

相关问题