数组元素之和最小化 | 豆包MarsCode AI刷题

93 阅读3分钟

问题描述

小C希望构造一个包含n个元素的数组,且满足以下条件:

  1. 数组中的所有元素两两不同。
  2. 数组所有元素的最大公约数为 k
  3. 数组元素之和尽可能小。

任务是输出该数组元素之和的最小值。


测试样例

样例1:

输入:n = 3 ,k = 1
输出:6

样例2:

输入:n = 2 ,k = 2
输出:6

样例3:

输入:n = 4 ,k = 3
输出:30

解题思路

1. 理解最大公约数为 k

这意味着数组中的每个元素都必须是 k 的倍数。因此,我们可以从 k 开始,逐步生成 k 的倍数。

2. 两两不同

为了确保数组中的元素两两不同,我们需要在生成倍数时检查是否已经存在于数组中。

3. 元素之和尽可能小

为了使数组元素之和尽可能小,我们应该从最小的 k 的倍数开始生成,直到生成 n 个不同的倍数。

算法步骤

  1. 初始化一个空列表 multiples 用于存储 k 的倍数。
  2. 从 k 开始,逐步生成 k 的倍数,直到生成 n 个不同的倍数。
  3. 检查生成的倍数是否已经存在于 multiples 列表中,如果不存在则添加到列表中。
  4. 计算 multiples 列表中所有元素的和,即为数组元素之和的最小值。
def solution(n: int, k: int) -> int:
    # 初始化一个列表来存储 k 的倍数
    multiples = []
    
    # 从 k 开始,生成 n 个不同的 k 的倍数
    current = k
    while len(multiples) < n:
        # 如果当前数不在列表中,添加到列表
        if current not in multiples:
            multiples.append(current)
        # 继续下一个 k 的倍数
        current += k
    
    # 计算这些倍数的和
    result = sum(multiples)
    
    return result

if __name__ == '__main__':
    print(solution(n = 3, k = 1) == 6)
    print(solution(n = 2, k = 2) == 6)
    print(solution(n = 4, k = 3) == 30)

个人易错点

在生成 k 的倍数时,确保每个元素只添加一次。当前代码中使用了 if current not in multiples 来检查重复,这在小规模数据下是可行的,但在大规模数据下可能会影响性能。

性能优化

当前代码的时间复杂度是 O(n^2),因为每次检查 current 是否在 multiples 中都需要线性时间。可以考虑使用集合(set)来存储 multiples,这样可以将检查重复的时间复杂度降低到 O(1)

优化后的代码:

def solution(n: int, k: int) -> int:
    # 初始化一个集合来存储 k 的倍数
    multiples = set()
    
    # 从 k 开始,生成 n 个不同的 k 的倍数
    current = k
    while len(multiples) < n:
        multiples.add(current)
        current += k
    
    # 计算这些倍数的和
    result = sum(multiples)
    
    return result

if __name__ == '__main__':
    print(solution(n = 3, k = 1) == 6)
    print(solution(n = 2, k = 2) == 6)
    print(solution(n = 4, k = 3) == 30)

补充知识点

  1. 集合(Set)的使用

    • 集合是一种无序且不重复的元素集合。使用集合可以高效地检查元素是否存在,因为集合的查找操作平均时间复杂度为 O(1)
  2. 最大公约数(GCD)

    • 最大公约数(Greatest Common Divisor,简称 GCD)是指两个或多个整数共有约数中最大的一个。

    例子

    • 对于整数 12 和 18,它们的公约数有 1, 2, 3, 6。其中最大的公约数是 6,所以 GCD(12, 18) = 6。 计算方法

    欧几里得算法(辗转相除法):

    • 这是一种高效的计算 GCD 的方法。其基本思想是:两个整数的最大公约数等于其中较小的数和两数相除余数的最大公约数。
    • 公式:GCD(a, b) = GCD(b, a % b),直到 b 为 0 时,a 即为最大公约数。
    • 代码实现:
    def gcd(a, b):
    while b != 0:
        a, b = b, a % b
    return a
    
  3. 数学优化

    • 在生成 k 的倍数时,可以直接从 k 开始,每次增加 k,而不需要检查重复。因为每次生成的倍数都是唯一的。

今天也是完成任务的一天呢!!

1732861633004.png