leetcode
leetcode 1901 ~ 1950
替换数组中的非互质数

替换数组中的非互质数

难度:

标签:

题目描述

代码结果

运行时间: 152 ms, 内存: 29.9 MB


/*
 * 题目思路:
 * 1. 使用Java Stream流处理来解决问题。
 * 2. 在处理流时找到相邻的非互质数对并进行替换。
 * 3. 使用Collector和reduction合并流。
 * 4. 返回最终的数组。
 */

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

public class SolutionStream {
    public List<Integer> replaceNonCoprimes(int[] nums) {
        return IntStream.of(nums)
                .boxed()
                .collect(Collectors.toCollection(ArrayList::new))
                .stream()
                .reduce(new ArrayList<>(), (acc, num) -> {
                    acc.add(num);
                    while (acc.size() > 1) {
                        int a = acc.get(acc.size() - 1);
                        int b = acc.get(acc.size() - 2);
                        int gcd = gcd(a, b);
                        if (gcd > 1) {
                            int lcm = lcm(a, b);
                            acc.remove(acc.size() - 1);
                            acc.remove(acc.size() - 1);
                            acc.add(lcm);
                        } else {
                            break;
                        }
                    }
                    return acc;
                }, (acc1, acc2) -> acc1);
    }

    private int gcd(int a, int b) {
        while (b != 0) {
            int temp = b;
            b = a % b;
            a = temp;
        }
        return a;
    }

    private int lcm(int a, int b) {
        return a / gcd(a, b) * b;
    }
}

解释

方法:

题解的思路是反复使用一个辅助函数 `re` 来处理数组,直到数组不再发生变化或者达到一定的迭代次数。辅助函数 `re` 的作用是从数组的末尾开始,逐个检查相邻的两个数是否互质,如果不是,则用它们的最小公倍数替换,直到数组头部。这种从后向前的处理方式是为了避免在处理过程中发生的元素替换影响到后续的处理。每次迭代后,都会检查数组长度是否发生变化,如果没有变化,则说明没有更多的非互质数对可以替换,处理过程结束。由于每次处理可能会改变数组的顺序,因此最后根据迭代次数的奇偶性决定是否需要反转数组以得到最终结果。

时间复杂度:

O(nlogn)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么题解中选择从数组的末尾开始处理而不是从头部开始?这种处理方式对结果有何影响?
从数组的末尾开始处理是因为在处理过程中,替换操作可能会影响到已经处理过的元素。如果从头部开始处理,每次替换可能会影响到后续的元素处理逻辑。而从末尾开始处理可以确保在处理当前元素时,该元素之前的部分已经被处理并确定下来,不会因为之后的操作而发生变化。这种方式有助于减少处理过程中的复杂性和潜在错误。
🦆
题解中提到的迭代次数固定为10次,这个数字是怎么确定的?是否有可能在10次迭代后仍未达到最终数组状态?
迭代次数固定为10次可能是基于经验或者在一般情况下的充分迭代次数假设。确实,存在特定的情况下,10次迭代仍可能无法达到最终数组状态,特别是在数组长度较大或数组中的数字范围较广时。在实际应用中,这个迭代次数可能需要根据具体问题的数据特性进行调整,以确保算法的正确性和效率。
🦆
在每次迭代中使用`gcd`函数计算最大公约数后直接计算最小公倍数,这种操作是否可能导致处理结果中的数值快速增大,从而影响计算性能?
使用`gcd`函数后计算最小公倍数确实可能导致处理结果中的数值快速增大,尤其是在非互质的数字较大时。由于最小公倍数是两个数的乘积除以它们的最大公约数,这可能导致结果数组中的数字迅速增长。这种增长会对计算性能产生影响,因为更大的数字需要更多的计算资源来处理。此外,数值的快速增长还可能导致整数溢出的问题,尤其是在编程语言中整数类型有固定上限的情况下。
🦆
题解中提到,如果迭代次数为奇数则直接返回数组,为偶数则返回反转后的数组。这种偶奇次数对返回结果的影响是基于什么逻辑?
这种偶奇次数的处理逻辑基于每次迭代后数组反转的操作。每次对数组进行`re`函数处理时,数组会先被反转,处理完成后再返回。因此,如果进行了奇数次迭代,最后一次处理后的数组相比原始数组是反转状态;如果进行了偶数次迭代,最后一次处理后的数组相比原始数组则是正常顺序。为了确保返回的数组与初始数组的顺序一致,需要根据迭代次数的奇偶性来决定是否对最终的数组进行反转。

相关问题