1. 问题背景与定义
今天遇到一道有趣的数组处理题目,题目要求我们找出给定整数数组中最长的"平衡子数组"。先明确几个关键概念:
- 子数组:数组中任意一段连续且非空的元素序列
- 平衡子数组:子数组元素去重后,偶数个数与奇数个数相等
比如数组 [2,1,2,3,4] 中:
[2,1,2]去重后为{2,1}(1奇1偶)是平衡的[1,2,3]去重后为{1,2,3}(2奇1偶)不平衡[2,3,4]去重后为{2,3,4}(1奇2偶)不平衡
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 解题思路分析
2.1 暴力解法可行性评估
最直观的思路是枚举所有可能的子数组,然后检查每个子数组是否满足平衡条件:
- 遍历所有可能的子数组起点i和终点j(i ≤ j)
- 对子数组nums[i..j]进行去重
- 统计去重后的奇偶数量
- 记录满足条件的最大子数组长度
时间复杂度分析:
- 子数组数量为O(n²)
- 每个子数组去重和统计需要O(n)
- 总复杂度O(n³)
对于n=1e5的大数组,这种解法显然不可行。
2.2 优化思路探索
我们需要找到一种线性或接近线性的解法。观察到:
- 去重性质:子数组的去重结果只与其中包含的不同元素有关
- 滑动窗口:可以考虑维护一个滑动窗口,动态跟踪窗口内元素的奇偶情况
- 哈希表记录:可以用哈希表记录元素最后一次出现的位置
关键突破点:
- 当遇到重复元素时,只需要考虑它最后一次出现的位置
- 维护当前窗口内奇数和偶数的计数
2.3 前缀和与哈希表结合
更优的思路是利用前缀和与哈希表:
- 将偶数视为+1,奇数视为-1(或相反)
- 计算前缀和数组prefix
- 当prefix[i] == prefix[j]时,说明i+1到j之间的子数组满足条件
- 使用哈希表记录每个前缀和第一次出现的位置
这种方法可以将时间复杂度降到O(n)。
3. Go语言实现详解
3.1 数据结构选择
go复制func longestBalancedSubarray(nums []int) int {
// 记录前缀和第一次出现的位置
prefixIndex := make(map[i
