以下是解决「统计优美子数组」问题的完整代码和详细解释。
---
### 解决方案
我们可以通过前缀和与哈希表的结合来高效地解决问题。以下是实现代码:
```python
def TEST_DO_NOT_CHANGE(nums, k):
# 初始化结果变量
rlt = 0
##########start下面可以改动
# 将奇数标记为1,偶数标记为0
prefix_sum = [0] * (len(nums) + 1)
for i in range(len(nums)):
prefix_sum[i + 1] = prefix_sum[i] + (nums[i] % 2)
# 使用哈希表记录前缀和出现的次数
count_map = {}
count_map[0] = 1 # 初始状态:前缀和为0的情况出现一次
for i in range(1, len(prefix_sum)):
current_sum = prefix_sum[i]
target = current_sum - k
if target in count_map:
rlt += count_map[target]
# 更新当前前缀和的计数
if current_sum in count_map:
count_map[current_sum] += 1
else:
count_map[current_sum] = 1
##########end 上面可以改动
return rlt
if __name__ == "__main__":
print(TEST_DO_NOT_CHANGE([1, 1, 2, 1, 1], 3)) # 输出: 2
print(TEST_DO_NOT_CHANGE([2, 4, 6], 1)) # 输出: 0
print(TEST_DO_NOT_CHANGE([2, 2, 2, 1, 2, 2, 1, 2, 2, 2], 2)) # 输出: 16
```
---
### 给出解释
#### 1. 问题分析
我们需要找到数组中所有包含 **恰好 `k` 个奇数** 的连续子数组的数量。直接枚举所有子数组的时间复杂度为 \(O(n^2)\),对于较大的输入会非常低效。因此,我们需要优化算法。
#### 2. 核心思想:前缀和 + 哈希表
- **前缀和**:我们可以将数组中的奇数标记为 `1`,偶数标记为 `0`,这样问题就转化为寻找前缀和之差等于 `k` 的子数组。
- **哈希表**:使用哈希表记录每个前缀和出现的次数,从而快速计算满足条件的子数组数量。
#### 3. 步骤详解
1. **构建前缀和数组**:
- 将原数组中的奇数替换为 `1`,偶数替换为 `0`。
- 构建前缀和数组 `prefix_sum`,其中 `prefix_sum[i]` 表示从数组开头到第 `i-1` 个元素的奇数个数。
2. **初始化哈希表**:
- 创建一个字典 `count_map`,用于记录每个前缀和出现的次数。
- 初始时,前缀和为 `0` 的情况出现一次(即空数组)。
3. **遍历前缀和数组**:
- 对于每个位置 `i`,计算当前前缀和 `current_sum`。
- 计算目标值 `target = current_sum - k`,表示我们需要找到的前缀和。
- 如果 `target` 存在于 `count_map` 中,则说明存在若干个子数组满足条件,累加其出现次数。
- 更新当前前缀和的计数到 `count_map` 中。
4. **返回结果**:
- 最终,变量 `rlt` 中存储的就是满足条件的子数组数量。
#### 4. 示例运行
##### 示例 1:
输入:`nums = [1, 1, 2, 1, 1], k = 3`
- 替换后的数组为 `[1, 1, 0, 1, 1]`。
- 前缀和数组为 `[0, 1, 2, 2, 3, 4]`。
- 满足条件的子数组为 `[1, 1, 2, 1]` 和 `[1, 2, 1, 1]`,总数为 `2`。
##### 示例 2:
输入:`nums = [2, 4, 6], k = 1`
- 替换后的数组为 `[0, 0, 0]`。
- 前缀和数组为 `[0, 0, 0, 0]`。
- 没有满足条件的子数组,总数为 `0`。
##### 示例 3:
输入:`nums = [2, 2, 2, 1, 2, 2, 1, 2, 2, 2], k = 2`
- 替换后的数组为 `[0, 0, 0, 1, 0, 0, 1, 0, 0, 0]`。
- 前缀和数组为 `[0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2]`。
- 满足条件的子数组总数为 `16`。
---
###