文章目录
- ⛏1. 题目
- 2. 算法原理
- ⚔解法一:暴力枚举
- ⚔解法二:前缀和+哈希表
- ⚒3. 代码实现
题目链接:525. 连续数组 - 力扣(LeetCode)
给定一个二进制数组 nums
, 找到含有相同数量的 0
和 1
的最长连续子数组,并返回该子数组的长度。
示例 1:
输入: nums = [0,1]
输出: 2
说明: [0, 1] 是具有相同数量 0 和 1 的最长连续子数组。
示例 2:
输入: nums = [0,1,0]
输出: 2
说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。
提示:
1 <= nums.length <= 105
nums[i]
不是 0
就是 1
直接枚举所有子数组,判断是否符合要求,这不做示例。
复杂度较高,大概率超时
这题的意思是让我们找出一个最长连续的区域,让这个区域内的0
和1
数量相等,如果我们直接统计这个0
和1
的数目的话,还是比较困难的。我们可以换个思路,反正这里就0
和1
两个数字,我们不妨将0
看作-1
,那么这题就转换成了在这个数组中,找出一段连续的区域,让这个区域内的和0
。
这样转换之后,就和这题类似:前缀和+哈希表——560. 和为 K 的子数组,这是这里找的是和为0
的最长子数组,那么这题就可以用前缀和+哈希表。
设i
为数组中的任意位置,用sum[i]
表示[0,i]
区间内的所有元素和,找到在[0,i-1]
位置第一次出现sum[i]
的位置即可
细节还是较多:
时间复杂度为O(n)
class Solution {
public:
int findMaxLength(vector<int>& nums)
{
unordered_map<int,int> hash;
hash[0] = -1; //默认前缀和为0的情况
int sum = 0,ret = 0;
for(int i=0;i<nums.size();i++)
{
sum+=nums[i]==0?-1:1;
if(hash.count(sum))
ret = max(ret,i-hash[sum]); //选取最长的子数组
else
hash[sum] = i;
}
return ret;
}
};