1. 问题背景与定义
今天遇到一道有趣的数组处理题目,题目要求我们找出给定整数数组中最长的"平衡子数组"。先明确几个关键概念:
- 子数组:数组中任意连续且非空的元素序列
- 平衡子数组:子数组中所有元素去重后,偶数与奇数的数量相等
举个例子,对于数组 [1,2,2,4],子数组 [2,2,4] 去重后得到 {2,4},包含2个偶数,0个奇数,不满足平衡条件;而子数组 [1,2] 去重后 {1,2} 有1奇1偶,就是平衡子数组。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 解题思路分析
2.1 暴力解法可行性评估
最直观的解法是枚举所有可能的子数组,然后检查每个子数组是否满足平衡条件。对于一个长度为n的数组:
- 子数组总数是n*(n+1)/2
- 每个子数组需要O(n)时间检查(去重+统计奇偶)
这样总时间复杂度是O(n³),对于n=1e5的数据显然不可行。
2.2 关键观察与优化方向
经过分析发现几个重要性质:
- 去重不影响奇偶统计:子数组去重后的奇偶统计,等同于该子数组中出现的不同奇数和不同偶数的数量
- 前缀差分的应用:可以维护两个哈希表,分别记录到当前位置为止出现的所有奇数和偶数
- 平衡条件的转化:平衡意味着(不同奇数数量 - 不同偶数数量)= 0
基于这些观察,我们可以设计一个O(n)的滑动窗口解法。
3. 算法设计与实现
3.1 滑动窗口解法
go复制func longestBalancedSubarray(nums []int) int {
n := len(nums)
maxLen := 0
oddSet := make(map[int]bool)
evenSet := make(map[int]bool)
left := 0
for right := 0; right < n; right++ {
num := nums[right]
if num%2 == 0 {
evenSet[num] = true
} else {
oddSet[num] = true
}
