leetcode 525 连续数组
一、题目描述
二、解题思路
整体思路
将数组中所有的0换成-1,找到含相同数量的0和1的最长连续子数组就可以转换为求和为0的子数组。枚举出以i位置为结尾的和为0的子数组,采用前缀和+哈希表的方法来解决这个问题。思路类似leetcode560和为K的子数组和leetcode974和可被K整除的子数组。
具体思路
要找出以i位置为结尾的和为0的子数组,即找出[0,i-1]内以和为sum-0,即和为sum的子数组,如图所示:
有以下细节问题需要注意:
(1)哈希表unordered_map<int,int>hash的键是前缀和,值是下标;
(2)前缀和加入哈希表的时机:
在计算i位置之前,哈希表里面只保存[0,i-1]区间的前缀和,所以,在完成if判断后,在将i位置的前缀和加入哈希表;
(3)子数组的长度为i-hash[sum],而不是i-hash[sum]+1,因为前缀和包含了右端点;
(4)如果整个向量的前缀和为0,为了避免出界,我们需要初始化hash[0]=-1;
(5)由于是求最长子数组的长度,所以如果键sum已经存在,则无需再更新hash[sum]的值,因为越靠左边,子数组长度越长;如果键sum不存在,则使得hash[sum]=i;
三、代码实现
时间复杂度:T(n)=O(n)
空间复杂度:S(n)=O(n)
class Solution {
public:int findMaxLength(vector<int>& nums) {//前缀和+哈希表unordered_map<int,int> hash;hash[0]=-1;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]);else hash[sum]=i;}return ret;}
};