1508. 子数组和排序后的区间和

计算所有连续子数组和的排序区间和 — 题解与实现

题目描述

给定一个数组 nums,包含 n 个正整数。需要计算该数组中所有非空的连续子数组的和,并将这些和组成的新数组进行升序排序。新数组的长度为:\frac{n \times (n + 1)}{2}

因为每个非空连续子数组都会对应一个和。

之后,要求计算排序后数组中从第 left 个数字到第 right 个数字(下标从 1 开始)的和,并将结果对 10^9 + 7 取模。


题目分析

  • 所有非空连续子数组和的个数:对于长度为 n 的数组,有多少个非空连续子数组呢?
    答案是 \frac{n \times (n + 1)}{2}。例如,长度为4的数组有10个非空连续子数组。

如何快速计算所有子数组的和?
计算所有子数组的和暴力方法是遍历所有 (i, j),求和;这会是 O(n^3) 的时间复杂度,很慢。
可以借助前缀和数组,令 prefix[i] 表示 nums[0]nums[i-1] 的和。这样任意子数组和可以在 O(1) 时间内得到:

  • \text{subarray\_sum}(i, j) = prefix[j+1] - prefix[i]
  • 排序与区间求和
    生成的所有子数组和存入一个数组,排序后即可按题目要求取区间 [left, right] 和。
  • 注意结果可能很大,需要对 10^9 + 7 取模

解题方法

1. 计算前缀和数组

构造一个长度为 n+1 的前缀和数组 prefix,其中:

  • prefix[0] = 0
  • prefix[i+1] = prefix[i] + nums[i]

2. 计算所有子数组和

遍历所有可能的子数组起点 i 和终点 j,利用前缀和快速计算:

sums.append(prefix[j+1] - prefix[i])

这一步时间复杂度为 O(n^2)。

3. 排序

对所有子数组和排序,时间复杂度 O(n^2 \log n^2) = O(n^2 \log n)

4. 取区间和并对结果取模

计算排序数组中 [left-1:right] 的和,然后对 10^9+7 取模返回。


代码示例(Python)

from typing import List

class Solution:
    def rangeSum(self, nums: List[int], n: int, left: int, right: int) -> int:
        MOD = 10**9 + 7
        
        # 1. 构造前缀和数组
        prefix = [0] * (n + 1)
        for i in range(n):
            prefix[i + 1] = prefix[i] + nums[i]
        
        # 2. 计算所有子数组和
        sums = []
        for i in range(n):
            for j in range(i, n):
                sums.append(prefix[j + 1] - prefix[i])
        
        # 3. 排序
        sums.sort()
        
        # 4. 取区间和并取模
        return sum(sums[left - 1:right]) % MOD

复杂度分析

  • 时间复杂度
    • 计算前缀和:O(n)
    • 生成所有子数组和:O(n^2)
    • 排序:O(n^2 \log n^2) = O(n^2 \log n)
    • 总体:O(n^2 \log n)
  • 空间复杂度
    • 前缀和数组:O(n)
    • 子数组和数组:O(n^2)

示例说明

以数组 nums = [1, 2, 3, 4] 为例:

  • 所有非空子数组和(共10个):
    • [1] = 1
    • [1, 2] = 3
    • [1, 2, 3] = 6
    • [1, 2, 3, 4] = 10
    • [2] = 2
    • [2, 3] = 5
    • [2, 3, 4] = 9
    • [3] = 3
    • [3, 4] = 7
    • [4] = 4

排序后:

  • [1, 2, 3, 3, 4, 5, 6, 7, 9, 10]
  • 若题目要求计算第 3 到第 6 个数的和,则区间是 [3, 3, 4, 5],和为 3 + 3 + 4 + 5 = 15。

总结与扩展

  • 该题最直观的解法是通过前缀和 + 全部枚举 + 排序实现。
  • 对于较大规模的数组,这种 O(n^2 \log n) 的算法可能性能不佳。
  • 如果要进一步优化,可以尝试利用二分法+优先队列的思路,按顺序找到第 k 小的子数组和,或者使用线段树等高级数据结构。
  • 但对于中小规模问题,这种暴力解法简单易懂,且实现方便。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值