[NEO解题报告]《Leetcode》525 -- 连续数组

1. 题目信息

1.1 题目描述

题目链接: 525. 连续数组

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

1.2 测试用例

示例 1:

输入: nums = [0,1]
输出: 2
说明: [0, 1] 是具有相同数量0和1的最长连续子数组。
  • 示例 2:
输入: nums = [0,1,0]
输出: 2
说明: [0, 1] (或 [1, 0]) 是具有相同数量0和1的最长连续子数组。
  • 示例 3:
输入: nums =[0,1,0,0,1,0,0,1,0,0,1,0]
输出: 4
  • 提示:
1 <= nums.length <= 105
nums[i] 不是 0 就是 1

2. 题目分析

说明, 今天的每日一题, 与昨天的有这惊人的相似; 建议先阅读一下昨天的题解:

2.1 前缀和+哈希存0/1出现的次数cnt

根据题意, 很容易想到前缀和来减少循环次数, 那我们这里的前缀和是对前面遇到的0、1进行求和吗?

假设一下, 如果是用前缀求和, 那么这个前缀和只能提现1的个数, 没法提现0的个数, 如果要判定两个下标区间的值是否满足要求, 就必须用公式 ( j − i + 1 ) = = 2 ∗ ( p r e v C n t I n d e x [ j ] − p r e v C n t I n d e x [ i ] ) (j-i+1) == 2 * (prevCntIndex[j]-prevCntIndex[i]) (ji+1)==2(prevCntIndex[j]prevCntIndex[i]) 来判定, 其中i < j, 这样还是需要两层循环遍历 O ( N 2 ) O(N^2) O(N2)

所以得想办法找个简单的值来标记是否中间的区间满足要求, 类似于 523 题目中的记录 余数的思想;

  • 前缀和 转换, 由于0、1需要配对, 所以可以用一个计数器cnt, 来标记0、1是否匹配;
    • 遇到 0 时 cnt--;
    • 遇到 1 时 cnt++
  • 哈希优化将每个新的cnt出现的位置存放到map中区,利用贪心思想只存首次出现的位置, 这样找出来的子数组就最长了;;

举例如下:

  • 给定一个数组ns=[0,1,0,0,1,0,0,1,0,0,1,0], 我们计算出来的cnt数组的关系为:
    • ns = [ 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0]
    • cs = [-1, 0,-1,-2,-1,-2,-3,-2,-3,-4,-3,-4]
  • 则根据cs计数相同的位置求差可以计算出子数组的长度, 比如: cs[0] == cs[4] == -1, 长度为4, 对应原始数组中的子数组为 [1, 0, 0, 1]

3. 代码详情

3.1 C++

3.1.1 前缀和+哈希存存0/1出现的次数cnt

// 执行用时:128 ms, 在所有 C++ 提交中击败了89.88%的用户
// 内存消耗:81.7 MB, 在所有 C++ 提交中击败了31.25%的用户
class Solution {
public:
    int findMaxLength(vector<int>& nums) {
        int n = nums.size();
        unordered_map<int, int> prevCntIndex;
        prevCntIndex[0] = -1;

        int cnt = 0;
        int ans = 0;
        for (int i = 0; i < n; i++) {
            if (nums[i]) {
                cnt++;
            } else {
                cnt--;
            }

            if (prevCntIndex.count(cnt)) {
                ans = max(ans, i - prevCntIndex[cnt]);
            } else {
                prevCntIndex[cnt] = i;
            }
        }
        
        return ans;
    }
};

3.2 Python

  • 与上面C++思路相同;
# 执行用时:212 ms, 在所有 Python3 提交中击败了98.70%的用户
# 内存消耗:19.6 MB, 在所有 Python3 提交中击败了28.57%的用户
class Solution:
    def findMaxLength(self, nums: List[int]) -> int:
        cnt = 0
        prevCntIndex = {0: -1}
        ans = 0
        for i, n in enumerate(nums):
            if n:
                cnt += 1
            else:
                cnt -= 1
            if cnt not in prevCntIndex:
                prevCntIndex[cnt] = i
            else:
                ans = max(ans, i - prevCntIndex[cnt])

        return ans

4. 系列文章

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逸云沙鸥のIHave@Dream

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值