1. 题目解析与核心思路
这道题目要求我们找出数组中所有和为k的连续子数组的个数。乍一看似乎很简单,但其中蕴含着几个需要特别注意的细节。
首先明确几个关键概念:
- 子数组必须是连续的,不能跳跃选取元素
- 数组中的元素可以是正数、负数或零
- 需要统计所有满足条件的子数组,包括可能重叠的子数组
1.1 暴力解法直观理解
最直观的解法就是暴力枚举所有可能的子数组,计算它们的和并与k比较。这种方法虽然简单直接,但时间复杂度高达O(n²),当数组长度较大时(比如超过10^4),性能会急剧下降。
暴力解法的核心在于双重循环:
- 外层循环确定子数组的起始位置i
- 内层循环从i开始累加元素,直到数组末尾
- 每次累加后检查当前和是否等于k
这种解法虽然效率不高,但对于理解问题和验证其他算法的正确性非常有帮助。
1.2 前缀和的概念引入
前缀和是一种常见的数组处理技巧,它能够将子数组求和问题转化为前缀和的差值问题。具体来说:
- 定义prefix[i]表示数组前i个元素的和(通常prefix[0]=0)
- 那么子数组nums[i..j]的和可以表示为prefix[j+1]-prefix[i]
这种转换的优势在于,我们只需要O(n)的时间预处理前缀和数组,之后就可以在O(1)时间内计算任意子数组的和。
1.3 哈希表优化的关键思路
前缀和优化虽然思路清晰,但时间复杂度仍然是O(n²)。进一步优化的关键在于:
我们实际上关心的是满足prefix[j]-prefix[i]=k的(i,j)对的数量。这可以重写为prefix[j]-k=prefix[i]。
因此,在遍历数组计算prefix[j]时,我们可以用一个哈希表记录之前所有prefix[i]出现的次数。这样,只需要检查哈希表中prefix[j]-k出现的次数,就能知道有多少个子数组以j结尾且和为k。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 暴力枚举法详细实现
2.1 算法流程详解
暴力解法的实现步骤如下:
- 初始化计数器count为0
- 外层循环遍历所有可能的起始位置i(0到n-1)
- 对于每个i,初始化当前和sum为0
- 内层循环从i开始遍历到数组末尾:
a. 将当前元素nums[j]加到sum中
b. 如果sum等于k,则count加1
