
文章目录
- ⛏1. 题目
- 🗡2. 算法原理
- ⚔解法一:暴力枚举
- ⚔解法二:前缀和+哈希表
- ⚒3. 代码实现
⛏1. 题目
题目链接:525. 连续数组 - 力扣(LeetCode)
给定一个二进制数组 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 <= 105nums[i]不是0就是1
🗡2. 算法原理
⚔解法一:暴力枚举
直接枚举所有子数组,判断是否符合要求,这不做示例。
复杂度较高,大概率超时
⚔解法二:前缀和+哈希表
这题的意思是让我们找出一个最长连续的区域,让这个区域内的0和1数量相等,如果我们直接统计这个0和1的数目的话,还是比较困难的。我们可以换个思路,反正这里就0和1两个数字,我们不妨将0看作-1,那么这题就转换成了在这个数组中,找出一段连续的区域,让这个区域内的和0。
这样转换之后,就和这题类似:前缀和+哈希表——560. 和为 K 的子数组,这是这里找的是和为0的最长子数组,那么这题就可以用前缀和+哈希表。
不了解的可以点击链接看一下这题:
设i为数组中的任意位置,用sum[i]表示[0,i]区间内的所有元素和,找到在[0,i-1]位置第一次出现sum[i]的位置即可

细节还是较多:
- 哈希表中存什么?
这里要的是最长的子数组,所以我们要的是下标,所以哈希表里面要建立前缀和与数组下标的映射关系.- 存入哈希表的时机:当这个下标对应的前缀和使用完毕之后,再丢入哈希表。
- 如果有重复的
<sum,i>,我们选取的是靠左侧的下标,因为我们选取的是最长子数组,越靠近左侧,这个子数组就越长
- 默认前缀和为
0时,应该去[-1,0]这个区间去找,所以当我们用hash[0] = -1来表示默认前缀和为0。- 长度计算,直接看下图,清晰明了:
时间复杂度为O(n)
⚒3. 代码实现
class Solution {
public:int findMaxLength(vector<int>& nums){unordered_map<int,int> hash;hash[0] = -1; //默认前缀和为0的情况int sum = 0,ret = 0;for(int i=0;i<nums.size();i++){sum+=nums[i]==0?-1:1;if(hash.count(sum))ret = max(ret,i-hash[sum]); //选取最长的子数组elsehash[sum] = i;}return ret;}
};
运行结果:



