一、 题目描述
给定一个二进制数组 nums , 找到含有相同数量的 0 和 1 的最长连续子数组,并返回该子数组的长度。
输入: nums = [0,1]
输出: 2
说明: [0, 1] 是具有相同数量 0 和 1 的最长连续子数组。
数据要求:
1 <= nums.length <= 10^5
nums[i] 不是 0 就是 1
0(N^2) 的复杂度达到了10 ^ 10 ,一般就会超时。
二、 算法思路
2.1 暴力解法
嵌套两个for循环直接搞定。
2.2 滑动窗口
- 何时 right 指针停止 ? 很显然 right 指针没法停止,因为他要找到最大的连续子数组;因此, left 指针也没法移动 , 因为一旦 left 移动就会导致累计求和的计算结果错误。
2.3 前缀和加map
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/A1NYOS/solution/0-he-1-ge-shu-xiang-tong-de-zi-shu-zu-by-xbyt/
来源:力扣(LeetCode)
三、 代码题解
3.1 暴力
class Solution {
public int findMaxLength(int[] nums) {
//暴力解法
int maxCount = 0;
for(int i = 0; i < nums.length; i++) {
int length = 0;
int count = 0;
count = nums[i] == 1 ? ++count : --count;
for(int j = i + 1; j < nums.length; j++) {
count = nums[j] == 1 ? ++count : --count;
if(count == 0) {
length = j - i + 1;
maxCount = Math.max(length,maxCount);
}
}
}
return maxCount;
}
}
前缀和+map:
class Solution {
public int findMaxLength(int[] nums) {
//前缀和加map
Map<Integer,Integer> map =new HashMap();
//作为一个辅助空间,来存储前缀和,并且作为前缀和加入到map中,如果map中有相同大小的前缀和::
//比如 第 i 个元素的前缀和与第 j 个元素的前缀和相等,那么证明从 i+1 到 j 这些元素的和为 0 ,所以才会出现
//前 i 个元素之和与前 j 个元素之和相同
int count = 0;
//这个是考虑到第一次前缀和等于0的情况:[0,1] 第一次前缀和为 0 此时 i 为 1;1- -1 = 2;
map.put(0,-1);
int maxLength = 0;
for(int i = 0; i < nums.length; i++) {
count = nums[i] == 1 ? ++count : --count;
if(map.containsKey(count)) {
maxLength=Math.max((i - map.get(count)),maxLength);
}else{
map.put(count,i);
}
}
return maxLength;
}
}