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

99 阅读4分钟

一、题目分析

本题要求构造一个包含 n 个元素的数组,同时需要满足三个关键条件:一是数组中的所有元素两两不同;二是数组所有元素的最大公约数为给定的 k;三是在满足前两个条件的基础上,要让数组元素之和尽可能小。最终任务是输出满足这些条件的数组元素之和的最小值。

二、解题思路探讨

  1. 关于最大公约数条件的思考
    既然要求数组所有元素的最大公约数为 k,那么可以设想数组中的每个元素都能写成 k 乘以某个整数的形式。例如,如果 k = 3,数组元素可以是 3×13×23×3 等等。这样构造出来的数组元素天然就保证了最大公约数是 k,满足题目条件中的第二条。
  2. 满足元素两两不同且和最小的策略分析
    为了让数组元素之和尽可能小,同时又要保证元素两两不同,我们可以采用一种比较自然的构造方式,即让数组元素分别为 k×1k×2k×3、……、k×n。这样的构造方式能保证每个元素都不同(因为乘的系数 1 到 n 各不相同),而且按照自然数从小到大的顺序去乘以 k,能使得整体的和相对最小。这是基于一种贪心的思想,从小的数开始选取,逐步构建满足条件的数组,期望最终得到的和是最小的。

三、具体解题步骤

  1. 计算基础自然数序列的和
    首先,我们需要计算从 1 到 n 这些自然数的和。数学上,计算 1 + 2 + 3 + … + n 的和有一个简洁的公式,即 n * (n + 1) // 2(这里使用 // 表示整除运算,在很多编程语言中可以这样来获取整数除法的结果)。这个公式的推导可以通过等差数列求和公式得到,首项 a₁ = 1,末项 aₙ = n,项数为 n,根据等差数列求和公式 Sₙ = (a₁ + aₙ) * n / 2,代入可得 Sₙ = (1 + n) * n / 2,化简后就是 n * (n + 1) // 2。我们把这个和记为 sum_of_first_n

  2. 得到满足条件数组元素之和的最小值
    由于前面分析得出数组元素构造为 k×1k×2k×3、……、k×n,所以整个数组元素之和就是 k 乘以从 1 到 n 这些自然数的和,也就是 k * sum_of_first_n

例如,当 n = 3k = 1 时:

  • 先计算 1 + 2 + 3 的和,根据公式可得 3 * (3 + 1) // 2 = 6,这就是基础自然数序列的和。

  • 再乘以 k(此时 k = 1),结果还是 6,这就是满足条件的数组元素之和的最小值,对应样例中的输出结果。

又如,当 n = 4k = 3 时:

  • 计算 1 + 2 + 3 + 4 的和,通过公式得到 4 * (4 + 1) // 2 = 10
  • 然后乘以 k(这里 k = 3),得出 30,也就是样例中输出的满足条件数组元素之和的最小值。
def solution(n: int, k: int) -> int:
    # 计算 1 + 2 + 3 + ... + n 的和
    sum_of_first_n = n * (n + 1) // 2
    # 乘以 k 得到最终的和
    return k * sum_of_first_n

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

四、复杂度分析

  1. 时间复杂度
    在整个解题过程中,主要进行了一次 n * (n + 1) // 2 的计算来获取从 1 到 n 自然数的和,这个计算操作涉及到简单的乘法和除法运算,其时间复杂度是常数级别的,不随输入的 n 和 k 的规模变化而变化,所以整体的时间复杂度为 。
  2. 空间复杂度
    代码中只使用了几个固定的变量(如 sum_of_first_n 等)来辅助计算,这些变量所占用的空间大小不会随着输入参数 n 和 k 的变化而改变,始终保持在常数级别,因此空间复杂度为 。