Medium
题目描述
给你一个整数数组 nums。
如果一个子数组中不同偶数的个数等于不同奇数的个数,则称该子数组为平衡的。
返回最长平衡子数组的长度。
示例 1:
输入:nums = [2,5,4,3]
输出:4
解释:
最长的平衡子数组是 [2, 5, 4, 3]。
它有 2 个不同的偶数 [2, 4] 和 2 个不同的奇数 [5, 3]。因此答案是 4。
示例 2:
输入:nums = [3,2,2,5,4]
输出:5
解释:
最长的平衡子数组是 [3, 2, 2, 5, 4]。
它有 2 个不同的偶数 [2, 4] 和 2 个不同的奇数 [3, 5]。因此答案是 5。
示例 3:
输入:nums = [1,2,3,2]
输出:3
解释:
最长的平衡子数组是 [2, 3, 2]。
它有 1 个不同的偶数 [2] 和 1 个不同的奇数 [3]。因此答案是 3。
提示:
1 <= nums.length <= 15001 <= nums[i] <= 10^5
提示:
- 使用暴力法
- 尝试每个子数组,使用映射/集合数据结构来跟踪不同的偶数和奇数
解题思路
解题思路
这道题要求找到最长的平衡子数组,其中平衡的定义是不同偶数个数等于不同奇数个数。
暴力枚举法(推荐)
由于数组长度最大为1500,我们可以使用暴力方法枚举所有可能的子数组:
- 双重循环:外层循环确定起始位置,内层循环确定结束位置
- 实时维护:在扩展子数组的过程中,使用两个集合分别记录当前子数组中的不同偶数和奇数
- 判断平衡:每次扩展后检查两个集合的大小是否相等,如果相等则更新最大长度
- 奇偶判断:通过
num % 2来判断数字的奇偶性
这种方法的优势在于:
- 逻辑清晰,易于理解和实现
- 在扩展子数组时实时维护状态,避免重复计算
- 时间复杂度虽然是O(n²),但在题目给定的数据范围内完全可行
优化思路
虽然暴力法已经足够,但也可以考虑其他优化方向:
- 使用哈希表记录状态差值,但由于需要区分不同数字,实现复杂度较高
- 分治法理论可行,但对于此题意义不大
综合考虑,暴力枚举法是最直观且高效的解决方案。
代码实现
class Solution {
public:
int longestBalanced(vector<int>& nums) {
int n = nums.size();
int maxLen = 0;
for (int i = 0; i < n; i++) {
unordered_set<int> evens, odds;
for (int j = i; j < n; j++) {
if (nums[j] % 2 == 0) {
evens.insert(nums[j]);
} else {
odds.insert(nums[j]);
}
if (evens.size() == odds.size()) {
maxLen = max(maxLen, j - i + 1);
}
}
}
return maxLen;
}
};
class Solution:
def longestBalanced(self, nums: List[int]) -> int:
n = len(nums)
max_len = 0
for i in range(n):
evens, odds = set(), set()
for j in range(i, n):
if nums[j] % 2 == 0:
evens.add(nums[j])
else:
odds.add(nums[j])
if len(evens) == len(odds):
max_len = max(max_len, j - i + 1)
return max_len
public class Solution {
public int LongestBalanced(int[] nums) {
int n = nums.Length;
int maxLen = 0;
for (int i = 0; i < n; i++) {
HashSet<int> evens = new HashSet<int>();
HashSet<int> odds = new HashSet<int>();
for (int j = i; j < n; j++) {
if (nums[j] % 2 == 0) {
evens.Add(nums[j]);
} else {
odds.Add(nums[j]);
}
if (evens.Count == odds.Count) {
maxLen = Math.Max(maxLen, j - i + 1);
}
}
}
return maxLen;
}
}
var longestBalanced = function(nums) {
let maxLen = 0;
for (let i = 0; i < nums.length; i++) {
let evenSet = new Set();
let oddSet = new Set();
for (let j = i; j < nums.length; j++) {
if (nums[j] % 2 === 0) {
evenSet.add(nums[j]);
} else {
oddSet.add(nums[j]);
}
if (evenSet.size === oddSet.size) {
maxLen = Math.max(maxLen, j - i + 1);
}
}
}
return maxLen;
};
复杂度分析
| 复杂度 | 分析 |
|---|---|
| 时间复杂度 | O(n²) |
| 空间复杂度 | O(n) |
时间复杂度说明: 双重循环遍历所有子数组,外层循环O(n),内层循环O(n),集合操作平均O(1)。
空间复杂度说明: 使用两个集合存储不同的偶数和奇数,最坏情况下存储所有元素,空间复杂度为O(n)。