Problem: 3719. 最长平衡子数组 I
文章目录
- [1. 整体思路](#1. 整体思路)
- [2. 完整代码](#2. 完整代码)
- [3. 时空复杂度](#3. 时空复杂度)
-
-
- [时间复杂度: O ( N 2 ) O(N^2) O(N2)](#时间复杂度: O ( N 2 ) O(N^2) O(N2))
- [空间复杂度: O ( N ) O(N) O(N)](#空间复杂度: O ( N ) O(N) O(N))
-
1. 整体思路
核心问题
在一个数组 nums 中,找到一个最长的连续子数组 nums[i...j],使得该子数组中奇数的种类数 与偶数的种类数 相等。
例如:[1, 2, 1, 4]。
- 子数组
[1, 2, 1]:奇数种类{1}(1种),偶数种类{2}(1种)。相等,长度 3。 - 子数组
[1, 2, 1, 4]:奇数种类{1}(1种),偶数种类{2, 4}(2种)。不相等。
算法逻辑
该解法使用了暴力枚举所有子数组的方法。
-
双重循环遍历:
- 外层循环
i从 0 到n-1,作为子数组的起始位置。 - 内层循环
j从i到n-1,作为子数组的结束位置。
- 外层循环
-
维护状态:
- 对于每个固定的起始位置
i,随着j向右移动,我们需要实时知道当前窗口[i, j]内奇数和偶数的种类数。 - 使用两个哈希表
HashMap<Integer, Integer>:odd:存储当前子数组中出现的奇数及其频次(其实只存频次是为了统计种类数size())。even:存储当前子数组中出现的偶数及其频次。
- 对于每个固定的起始位置
-
判断与更新:
- 每当
j移动一步,将nums[j]加入对应的哈希表。 - 检查
odd.size() == even.size()。如果相等,说明当前子数组是"平衡"的。 - 更新全局最大长度
ans。
- 每当
2. 完整代码
java
import java.util.HashMap;
class Solution {
public int longestBalanced(int[] nums) {
int n = nums.length;
// 记录最长平衡子数组的长度,初始为 0
int ans = 0;
// 外层循环:枚举所有可能的子数组起始位置 i
for (int i = 0; i < n; i++) {
// 对于每个起始位置 i,我们需要重新统计奇偶数的种类
// 使用两个哈希表来记录窗口内的元素
// key: 数值, value: 出现次数 (本题逻辑只关心 key 是否存在,value 其实可以省略或者用 HashSet)
HashMap<Integer, Integer> odd = new HashMap<>();
HashMap<Integer, Integer> even = new HashMap<>();
// 内层循环:枚举所有可能的子数组结束位置 j
// 随着 j 增加,窗口 [i, j] 向右扩展
for (int j = i; j < n; j++) {
// 判断当前元素 nums[j] 是奇数还是偶数,并加入对应的集合
if (nums[j] % 2 == 0) {
// 偶数
even.put(nums[j], even.getOrDefault(nums[j], 0) + 1);
} else {
// 奇数
odd.put(nums[j], odd.getOrDefault(nums[j], 0) + 1);
}
// 核心判断条件:奇数种类数 == 偶数种类数
// 注意:这里比较的是 size(),即不同数值的个数,而不是总个数
if (odd.size() == even.size()) {
// 更新最大长度
ans = Math.max(ans, j - i + 1);
}
}
}
return ans;
}
}
3. 时空复杂度
假设数组 nums 的长度为 N N N。
时间复杂度: O ( N 2 ) O(N^2) O(N2)
- 计算依据 :
- 代码包含两层嵌套循环。
- 外层循环执行 N N N 次。
- 内层循环平均执行 N / 2 N/2 N/2 次。
- 哈希表的操作(插入、查询 size)平均时间复杂度为 O ( 1 ) O(1) O(1)。
- 总操作次数约为 N ( N + 1 ) 2 \frac{N(N+1)}{2} 2N(N+1)。
- 结论 : O ( N 2 ) O(N^2) O(N2)。
- 对于 N ≤ 1000 N \le 1000 N≤1000 或 2000 2000 2000 的数据规模,这个解法是可以接受的。但如果 N N N 较大(如 10 5 10^5 105),则会超时。
空间复杂度: O ( N ) O(N) O(N)
- 计算依据 :
- 在最坏情况下(所有元素都不同),两个哈希表可能会存储 O ( N ) O(N) O(N) 个键值对。
- 虽然哈希表是在循环内部创建的,但每次内层循环都会重新分配空间,最大占用为 O ( N ) O(N) O(N)。
- 结论 : O ( N ) O(N) O(N)。