题目
链接:leetcode
思路分析(前缀和)
首先介绍一个小技巧
在处理二进制数组的时候,因为数组里面只有0和1,我们可以将所有的0变成-1
这个时候1和-1之间就可以产生很多抵消,有利于处理数组。
在该题中,要寻找一个连续子数组,使得其中含有相同数量的0和1,0变成-1之后,也就是,含有相同数量的-1和1,
那么这个区间的和就是0
分析到这里,相信读者可以联想到前面的一道题
传送门:和为K的子数组
在这道题目里面就是和为0的子数组
也就是我们需要再 [0 , i - 1] 这个区间里面寻找一个最短的前缀和等于 sum - 0
处理的大体思路类似,依旧采用前缀和+哈希表来处理。
细节:
- 哈希表里面存什么?
哈希表里面存前缀和和这个前缀和最早出现的下标- 什么时候插入哈希表
当然是先查找,再插入- 对于[0 , i ]区间正好有相同个0和1如何处理
也就是这个时候我们需要特殊区处理hash[0],hash[0]的下标固定给-1,来应对整个区间正好有相同个0和1的情况- 如何求最长连续子数组的长度
直接用当前位置的下标 - 前缀和对应的下标 (千万不要再加1,我们不需要包括前缀和的最后一个元素)- 遇到重复的前缀和怎么处理
遇到重复的前缀和,只记录前缀和第一次出现时的下标,才能,满足最长连续子数组
代码
int findMaxLength(vector<int>& nums) {
//类似和为K的最长子数组--和为0的最长子数组
unordered_map<int,int> hash;//sum 和 下标
hash[0] = -1;
int sum = 0,len = 0;
for(int i = 0;i < nums.size();++i)
{
if(nums[i] == 0) nums[i] = -1;//0和1不好处理,换成1和-1非常好处理
sum += nums[i];
if(hash.count(sum))
len = max(len, i - hash[sum]);
if(!hash.count(sum)) hash[sum] = i;//统计最早出现的
}
return len;
}