AI 刷题 214. 小R的权值计算 | 豆包MarsCode AI刷题

58 阅读4分钟

问题描述

小R定义了一个长度为 m 的数组 b 的权值为:1×b_1 + 2×b_2 + 3×b_3 + ... + m×b_m

现在小R有一个长度为 n 的数组 a,她想知道所有子数组的权值和是多少,并且答案需要对 10^9 + 7 取模。

测试样例

样例1:

输入:n = 3, a = [1, 2, 3]
输出:33

样例2:

输入:n = 4, a = [4, 5, 6, 7]
输出:203

样例3:

输入:n = 2, a = [10, 20]
输出:80

分析

问题理解

题目要求我们计算一个长度为 n 的数组 a 的所有子数组的权值和,并且对结果取模 10^9 + 7。子数组的权值定义为:1×b_1 + 2×b_2 + 3×b_3 + ... + m×b_m,其中 b 是子数组,m 是子数组的长度。

数据结构的选择逻辑

  1. 数组:我们使用数组 a 来存储输入数据。
  2. 子数组:子数组是数组 a 的连续子序列。

算法步骤

  1. 遍历所有子数组:我们需要遍历所有可能的子数组。对于每个子数组,计算其权值。
  2. 计算权值:对于每个子数组 b,计算其权值 1×b_1 + 2×b_2 + 3×b_3 + ... + m×b_m
  3. 累加权值:将每个子数组的权值累加到总权值和 total_weight 中。
  4. 取模操作:在每次累加时,对结果取模 10^9 + 7 以防止溢出。

难点分析

  1. 子数组的遍历:遍历所有子数组的时间复杂度是 O(n^3),因为我们需要三重循环:外层循环确定子数组的起始位置,中层循环确定子数组的结束位置,内层循环计算子数组的权值。
  2. 权值的计算:对于每个子数组,我们需要计算其权值。这个计算过程本身是线性的,但因为子数组的数量非常多,整体的时间复杂度会非常高。
  3. 取模操作:在每次累加时,需要对结果取模 10^9 + 7,以防止溢出。这个操作需要小心处理,确保不会因为溢出导致结果错误。
  4. 优化空间:直接遍历所有子数组会导致时间复杂度过高,需要考虑如何优化算法,减少不必要的计算。

优化思路

  1. 动态规划:可以考虑使用动态规划来减少重复计算。例如,可以记录每个位置的贡献,避免重复计算子数组的权值。
  2. 前缀和:使用前缀和数组来快速计算子数组的和,从而减少计算权值的时间复杂度。

代码

def solution(n: int, a: list) -> int:
    MOD = 10**9 + 7
    
    # 初始化总权值和
    total_weight = 0
    
    # 遍历所有可能的子数组
    for start in range(n):
        for end in range(start, n):
            # 计算当前子数组的权值
            current_weight = 0
            for i in range(start, end + 1):
                current_weight += (i - start + 1) * a[i]
            
            # 累加到总权值和
            total_weight = (total_weight + current_weight) % MOD
    
    return total_weight

if __name__ == '__main__':
    print(solution(3, [1, 2, 3]) == 33)
    print(solution(4, [4, 5, 6, 7]) == 203)
    print(solution(2, [10, 20]) == 80)

解法分析

  1. 初始化总权值和:使用变量 total_weight 来存储所有子数组的权值和。
  2. 遍历所有子数组:使用两个嵌套循环来遍历所有可能的子数组。外层循环确定子数组的起始位置 start,内层循环确定子数组的结束位置 end
  3. 计算当前子数组的权值:对于每个子数组 a[start:end+1],使用一个内层循环计算其权值 current_weight
  4. 累加权值:将每个子数组的权值累加到 total_weight 中,并在每次累加时对结果取模 10^9 + 7

时间复杂度分析

  • 外层循环:遍历所有可能的起始位置 start,时间复杂度为 O(n)
  • 中层循环:对于每个起始位置 start,遍历所有可能的结束位置 end,时间复杂度为 O(n)
  • 内层循环:对于每个子数组 a[start:end+1],计算其权值,时间复杂度为 O(n)

因此,总的时间复杂度为 O(n^3)

空间复杂度分析

  • 额外空间:除了输入数组 a 外,只使用了常数级别的额外空间(如 total_weightcurrent_weight),因此空间复杂度为 O(1)