前缀和+哈希表——525. 连续数组

前缀和+哈希表——525. 连续数组_第1张图片

文章目录

    • ⛏1. 题目
    • 2. 算法原理
      • ⚔解法一:暴力枚举
      • ⚔解法二:前缀和+哈希表
    • ⚒3. 代码实现

⛏1. 题目

题目链接:525. 连续数组 - 力扣(LeetCode)

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

示例 1:

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

示例 2:

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

提示:

  • 1 <= nums.length <= 105
  • nums[i] 不是 0 就是 1

2. 算法原理

⚔解法一:暴力枚举

直接枚举所有子数组,判断是否符合要求,这不做示例。

复杂度较高,大概率超时

⚔解法二:前缀和+哈希表

这题的意思是让我们找出一个最长连续的区域,让这个区域内的01数量相等,如果我们直接统计这个01的数目的话,还是比较困难的。我们可以换个思路,反正这里就01两个数字,我们不妨将0看作-1,那么这题就转换成了在这个数组中,找出一段连续的区域,让这个区域内的和0

这样转换之后,就和这题类似:前缀和+哈希表——560. 和为 K 的子数组,这是这里找的是和为0的最长子数组,那么这题就可以用前缀和+哈希表

不了解的可以点击链接看一下这题:
前缀和+哈希表——525. 连续数组_第2张图片

i为数组中的任意位置,用sum[i]表示[0,i]区间内的所有元素和,找到在[0,i-1]位置第一次出现sum[i]的位置即可
前缀和+哈希表——525. 连续数组_第3张图片

细节还是较多:

  • 哈希表中存什么?
    这里要的是最长的子数组,所以我们要的是下标,所以哈希表里面要建立前缀和与数组下标的映射关系.
  • 存入哈希表的时机:当这个下标对应的前缀和使用完毕之后,再丢入哈希表。
  • 如果有重复的,我们选取的是靠左侧的下标,因为我们选取的是最长子数组,越靠近左侧,这个子数组就越长
    前缀和+哈希表——525. 连续数组_第4张图片
  • 默认前缀和为0时,应该去[-1,0]这个区间去找,所以当我们用hash[0] = -1来表示默认前缀和为0
  • 长度计算,直接看下图,清晰明了:
    前缀和+哈希表——525. 连续数组_第5张图片

时间复杂度为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]);	//选取最长的子数组
            else
                hash[sum] = i;
        }
        return ret;
    }
};

运行结果:
前缀和+哈希表——525. 连续数组_第6张图片

你可能感兴趣的:(原创,刷题,散列表,数据结构,前缀和,算法)