数组的三角和

标签: 数组 数学 组合数学 模拟

难度: Medium

给你一个下标从 0 开始的整数数组 nums ,其中 nums[i] 是 0 到 9 之间(两者都包含)的一个数字。

nums 的 三角和 是执行以下操作以后最后剩下元素的值:

  1. nums 初始包含 n 个元素。如果 n == 1 ,终止 操作。否则,创建 一个新的下标从 0 开始的长度为 n - 1 的整数数组 newNums 。
  2. 对于满足 0 <= i < n - 1 的下标 i ,newNums[i] 赋值 为 (nums[i] + nums[i+1]) % 10 ,% 表示取余运算。
  3. 将 newNums 替换 数组 nums 。
  4. 从步骤 1 开始 重复 整个过程。

请你返回 nums 的三角和。

示例 1:

输入:nums = [1,2,3,4,5]
输出:8
解释:
上图展示了得到数组三角和的过程。

示例 2:

输入:nums = [5]
输出:5
解释:
由于 nums 中只有一个元素,数组的三角和为这个元素自己。

提示:

  • 1 <= nums.length <= 1000
  • 0 <= nums[i] <= 9

Submission

运行时间: 52 ms

内存: 16.2 MB

class Solution:
    def triangularSum(self, nums: List[int]) -> int:
        c, res = 1, nums[0]
        for i in range(1, len(nums)):
            c = c * (len(nums) - i) // i
            res = (res + c * nums[i]) % 10
        return res

Explain

该题解采用的是一种基于组合数学的方法,利用了二项式系数。基本思路是将每一次的数组变换转换为一个组合数学问题。对于数组中的每个元素nums[i],它在最终结果中的贡献是通过组合系数来确定的。具体来说,每个元素nums[i]会被组合系数c加权,这个系数c是从组合数学中的二项式系数计算得到的,表示从n-1个元素中选取i个元素的组合方式的数量。这个系数随着i的增加而更新,每次使用组合公式 c = c * (len(nums) - i) // i 来计算。最终,所有元素的加权和模10的结果即为答案。

时间复杂度: O(n)

空间复杂度: O(1)

class Solution:
    def triangularSum(self, nums: List[int]) -> int:
        c, res = 1, nums[0]  # 初始化组合系数c为1,结果res为数组的第一个元素
        for i in range(1, len(nums)):
            c = c * (len(nums) - i) // i  # 更新组合系数c
            res = (res + c * nums[i]) % 10  # 计算当前的结果并取模10
        return res  # 返回最终的结果

Explore

在题解中,二项式系数对应于数组在每次变换中的元素组合方式。二项式系数表达了在多项式展开中,每个项的系数,这里类似地用于计算数组中每个元素对结果的贡献。具体来说,在每次变换后,原数组的元素通过组合的方式贡献到新生成的元素上。例如,在一个长度为n的数组中,组合系数c表示选择i个元素的组合数,即从n-1个元素中选i个的方式。这个系数随着变换的进行而更新,用以确保每个元素的贡献被正确计算。

这个公式源自组合数学中的组合系数的递推关系。在组合数学中,C(n, k) = C(n-1, k-1) + C(n-1, k)。在计算连续的组合系数时,可以使用C(n, k) = C(n, k-1) * (n - k + 1) / k来简化计算。题解中的公式`c = c * (len(nums) - i) // i`实际上是这个递推式的应用,通过从前一个组合系数直接计算下一个,避免了重复的计算工作,提高了效率。

初始设置组合系数c为1是因为在组合数学中,任何数的0次组合数(C(n, 0))都是1。这是组合系数计算的基础。初始结果res设置为nums[0]是因为在数组的第一次变换中,第一个元素的贡献是未经任何组合直接被累加的,因此它的组合系数应该是1。这样的初始化确保了在后续的迭代中,每个元素的贡献都按正确的组合系数进行计算。

在数组的每次变换中,基于组合系数和当前元素的乘积计算贡献,并累加到结果中。由于结果需要在一个较小的数字范围(例如模10的结果),每次累加后都进行取模操作,确保结果保持在0到9的范围内。这种累加和取模的方式有效地实现了多次变换的累积效果,并且避免了大数的处理,使得算法更加高效和稳定。