leetcode-525-连续数组

连续数组

题面

leetcode题目

给定一个二进制数组 \(nums\) , 找到含有相同数量的 \(0\)\(1\) 的最长连续子数组,并返回该子数组的长度。

example

输入: \(nums = [0,1]\)
输出: \(2\)
说明: \([0, 1]\) 是具有相同数量0和1的最长连续子数组。

数据范围

  • \(1 <= nums.length <= 10^5\)
  • \(nums[i]\) 不是 \(0\) 就是 \(1\)

题解

总体思路

这个题目都想不到前缀和维护就太离谱了。
为了方便我们令下标从1开始计算,维护\(sum_1[i]\)表示\(nums[1],nums[2],nums[3]\cdots nums[i]\)\(1\)的个数,那么很自然的 \[sum_0[i] = i - sum_1[i] \tag{1}\] 题目要求 \[ sum_1[i] - sum_1[j] = sum_0[i] - sum_0[i] \tag{2}\] 我们合并\((1)\)\((2)\)式,可以得到: \[ sum_1[i] -sum_1[j] = i - sum_1[i] - j + sum_1[j] \tag{3}\] 很自然的,我们需要探求\(sum_1[i]\)\(sum_1[j]\)的关系,所以我们这样整理式子: \[ 2\times sum_1[i] - i = 2\times sum_1[j] -j \tag{4}\]\((4)\)式我们可知,满足此条件的\(i\)\(j\)之间构成的子数组(注意不含j),满足题目要求,显然我们可以维护一个哈希表来表示最远端的满足\((4)\)式的值。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <cstring>
using namespace std;

#define _DEBUG
class Solution
{
public:
int findMaxLength(vector<int> &nums)
{
int len = nums.size();
int sum[len + 1];
sum[0] = 0;
map<int, int> idxMap;
idxMap[0] = 0;
int max = 0;
for (int i = 1; i <= len; i++)
{
int num = nums[i - 1];
if (num == 1)
{
sum[i] = sum[i - 1] + 1;
}
else
{
sum[i] = sum[i - 1];
}
int tmp = 2 * sum[i] - i;
#ifdef _DEBUG
cout << "i: " << i << " sum[i]: " << sum[i] << " tmp: " << tmp << endl;
#endif
if (idxMap.count(tmp) != 0)
{
int preIdx = idxMap[tmp];
int subLen = i - preIdx;
if (subLen > max)
{
max = subLen;
}
}
else
{
idxMap[tmp] = i;
}
}
return max;
}
};

// for test
int main()
{
Solution s;
vector<int> nums1{0, 1};
cout << s.findMaxLength(nums1) << endl;
vector<int> nums2{0, 1, 0};
cout << s.findMaxLength(nums2) << endl;
return 0;
}
作者

Yu Leng

发布于

2021-06-03

更新于

2024-10-28

许可协议

评论