525. 连续数组
题目
给定一个二进制数组
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 <= 10^5
nums[i]
不是0
就是1
思路
方法一(前缀和,暴力方法,超时)
设置一个与给定数组规模一样的数组arr
,arr
中第i
个元素arr[i]
表示原数组nums
中,0 ~ i
中0的个数。
要求i ~ j
中0的个数,即arr[j] - arr[i - 1]
,注意当i = 0
时,i ~ j
中0的个数即是 arr[j]
。要求 0 和 1 个数相同的子数组,即i ~ j
中0的个数等于1的个数,i ~ j
中元素个数为 j - i + 1
,因为数组中元素不是0 就是1 所以i ~ j
中1的个数为: j - i + 1 - 0的个数
。当两者相等时求出长度,遍历过后得出最大长度maxLen
。
代码实现
int findMaxLength(int* nums, int numsSize){
//为数组分配内存
int* arr = malloc(sizeof(int) * numsSize);
//记录当前的最大长度,count用于记录0的个数
int maxLen = 0,count = 0;
int i = 0, j = 0;
//遍历一次,记录0的个数
for(i = 0; i < numsSize; i ++){
if(0 == nums[i]){
count++;
}
arr[i] = count;
}
for(i = 0; i < numsSize; i++){
for(j = i + 1; j < numsSize; j++){
//i ~ j 0的个数
int zeroNum = 0;
if(0 == i){ // i 等于0时,i~j 0的个数即是 0 ~ j -> arr[j]
zeroNum = arr[j];
}else{
zeroNum = arr[j] - arr[i - 1];
}
// 1的个数
int oneNum = j - i + 1 - zeroNum;
//当0 的个数和1的个数相等时,获取当前长度和最大长度比较
if(oneNum == zeroNum){
int len = j - i + 1;
if(len > maxLen)
maxLen = len;
}
}
}
//回收内存
free(arr);
return maxLen;
}
方法二(哈希,前缀和)
设置一个flag
来记录现在已经出现过的1和0的个数,遇1加一,遇0减一. 遍历整个nums数组, 变化flag
的值, 只要当flag==0
时 即达成了题目的要求 ,而且长度是i+1
肯定是目前出现过的最大长度,故直接赋值给maxLen
.
当flag != 0
时,有两种情况,flag > 0
即 1多了,此时我们需要去找之前是否出现过的有和现在flag
值相等的情况。如果这个值存在,假设对应下标为 index
,那么当前下标i - index
得到的就是我们的目标子数组长度,因为如果index
和i对应的值相等,那么0 ~ index
和 0 ~ i
中多出的1的个数是相等的,那么在i - index
中就是满足条件的子数组。当flag < 0
时同理。
那么便可以用哈希表来解决,但C语言实现哈希表相对困难些,目前我也没学习相关内容。在根据题目要求,数组长度为 1~10^5 那么flag
的取值范围:-50000<flag<50000
我们只需要构建两个数组分别记录 0 和 1的对应情况即可模拟哈希表。当遍历过程中出现某个flag
值时:
-
首先查看是否为 0 若是为 0则,maxLen = i + 1,继续下一次循环
-
若不等于0则:
-
查看当前哈希表是否存在
flag
值与当前相同的项,如果存在,哈希表存放的是这个值第一次出现的下标 ,将当前遍历下标i减去哈希表中存放的下标即为当前满足要求的子数组长度,与maxLen
值比较并赋值, -
如果不存在则将这个
flag
值记录在哈希表中。
-
代码实现
int findMaxLength(int* nums, int numsSize) {
int one[50000];
int zero[50000];
int value = 0, i = 0, maxLen = 0;
memset(one, -1, sizeof(one));
memset(zero, -1, sizeof(zero));
for (i = 0; i < numsSize; i++) {
if (nums[i] == 0)
value--;
else
value++;
if (0 == value) {
maxLen = i + 1;
}else {
if (value < 0) {
if (zero[abs(value)] == -1) {
zero[abs(value)] = i;
}
else{
if (i - zero[abs(value)] > maxLen) {
maxLen = i - zero[abs(value)];
}
}
}else {
if (one[value] == -1)
{
one[value] = i;
}
else {
if (i - one[value] > maxLen)
{
maxLen = i - one[value];
}
}
}
}
}
return maxLen;
}