011、0和1数量相同的子数组
给定一个二进制数组 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
思路
前缀和+哈希表解题
1、首先题目要求找到0和1数量相等的最长子数组,我们可以把0看做-1,这样就变成了找到一个最长的子数组使得数组里面的元素和为0。我们把nums=[0,1,0,1,1]看做nums=[-1,1,-1,1,1]。(下面以这个为例)
2、依次求得前n个整数的和sum
| n | sum |
|---|---|
| 0 | 0 |
| 1 | -1 |
| 2 | 0 |
| 3 | -1 |
| 4 | 0 |
| 5 | 1 |
根据这个表我们可以发现规律:当sum值相等时,我们用其对应的n值相减,得到的就是一个数组内各元素和为0的数组
例如n=1和n=3的sum都是-1,
所以我们用 [-1,1,-1,1,1] - [-1,1,-1,1,1] = [-1,1,-1,1,1]

得到的这个sum为0的子数组就是一个符合题目要求的子数组
3、建立一个哈希表来存放这些前缀和
Map<Integer, Integer> map = new HashMap<>();
map.put(0, 0);//先把前0和数的前缀和放进哈希表
| key | value |
|---|---|
| 0 | 0 |
遍历数组
int sum=0;
int ans=0;
```
for(int i = 0; i < nums.length; i++)
sum += nums[i] == 0 ? -1 : 1;
如果哈希表中不存在key值为sum,map.put(sum, i + 1);
| key | value |
|---|---|
| 0 | 0 |
| -1 | 1 |
如果哈希表中存在key为sum,
ans = Math.max(ans, i+1-map.get(sum));
因为我们要求的是最大的子数组的长度,所以key值相同的情况下我们只需保留小的value
代码
public int findMaxLength(int[] nums) {
int ans=0;//返回值
int sum=0;//和
Map<Integer, Integer> map = new HashMap<>();
map.put(0, 0);//前0个整数sum为0
for (int i = 0; i < nums.length; i++) {
sum += nums[i] == 0 ? -1 : 1;//把0当成-1
//哈希表中是否存在key值为sum
if (map.containsKey(sum)) {
ans = Math.max(ans, i+1-map.get(sum));
} else {
map.put(sum, i + 1);
}
}
return ans;
}

浙公网安备 33010602011771号