题目
给定一个二进制数组 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的个数存到前缀和数组中。假如 n u m s [ j . . . i ] nums[j...i] nums[j...i]中 0 0 0和 1 1 1的个数相同,即有 1 1 1的个数是区间长度的 1 / 2 1/2 1/2,即 1 / 2 ( i − j + 1 ) 1/2(i-j+1) 1/2(i−j+1),故有 s u m [ i ] − s u m [ j − 1 ] = 1 / 2 ( i − j + 1 ) sum[i]-sum[j-1]=1/2(i-j+1) sum[i]−sum[j−1]=1/2(i−j+1),移项得 2 s u m [ i ] − i = 2 s u m [ j − 1 ] − ( j − 1 ) 2sum[i]-i=2sum[j-1]-(j-1) 2sum[i]−i=2sum[j−1]−(j−1),因此记录 2 s u m [ i ] − i 2sum[i]-i 2sum[i]−i即可。因为题目要求最长区间,因此用哈希表来维护 2 s u m [ i ] − i 2sum[i]-i 2sum[i]−i对应的最左边的 i i i值。
代码
class Solution {
public:
int findMaxLength(vector<int>& nums) {
int n = nums.size();
vector<int>sum(n+1);
for(int i=1;i<=n;i++){
sum[i]=sum[i-1]+nums[i-1];
}
int ans=0;
map<int,int>mp;
mp[0]=0;
for(int i=1;i<=n;i++){
int s=2*sum[i]-i;
if(mp.count(s)){
ans=max(ans,i-mp[s]);
}else{
mp[s]=i;
}
}
return ans;
}
};