[M前缀和] lc525. 连续数组(前缀和+知识理解+思维)

1. 题目来源

链接:525. 连续数组

2. 题目解析

前缀和变种,思维型题目。

在此 s[i] 定义为,前 i 个数中,1 的个数减去 0 的个数的差值。在此定义下,[j,i] 区间的 1 的个数减去 0 的个数的差值就是 s[i]-s[j-1]是满足前缀和的推导公式的,也可以看作是容斥原理。

那么针对 i 位置,以 i 位置为终点,j 为起点,若能构成答案,则必然有 s[i]-s[j-1]=0 即 1 的个数与 0 的个数相等,即 s[i]=s[j-1]

故相当于统计 i 位置之前是否存在与 s[i] 相等的位置即可。且在此需要求的是区间长度,故哈希表统计两个值 :s[j],j,首先在哈希表中 hs[0]=0,作为边界。

顺序枚举 i,如果哈希表中存在 s[i] 值相等的话,就是满足条件的答案区间,可以更新答案。如果不存在 s[i] 值相等的话,说明 s[i] 是第一次出现,对应的 i 位置也是第一次出现的最小下标,故更新 hs[s[i]] = i


知识理解:

注意前缀和需要深刻理解下标这个概念,[j, i] 区间 1 和 0 的差值是 s[i]-s[j-1]。再进一步,[i,i] 这个区间,其长度是 1,其 1 和 0 的差值是 s[i]-s[i-1]

我们在下标存储的时候是针对 s[i] 存的 i 下标,那么针对 s[i-1] 就存的是 i-1 这个下标。对应的 s[j-1] 存的就是 j-1 这个下标。

那么当我们找到和 s[i] 相等的值的时候,计算区间长度,按理说是左端点减右端点再 +1 的,但是针对前缀和这种特殊的问题来讲,若 s[i]=s[j] 其实是 [j+1,i] 区间是答案,故可以直接进行 i-j 就等价于 i-(j+1)+1 作为区间长度了。


时间复杂度: O ( n ) O(n) O(n)

空间复杂度: O ( n ) O(n) O(n)


class Solution {
public:
    int findMaxLength(vector<int>& nums) {
        int n = nums.size();
        unordered_map<int, int> hs;
        hs[0] = 0;
        int res = 0;
        for (int i = 1, one = 0, zero = 0; i <= n; i ++ ) {
            int x = nums[i - 1];
            if (x) one ++ ;
            else zero ++ ;
            
            int s = one - zero;
            if (hs.count(s)) res = max(res, i - hs[s]); // 前缀和求区间长度不需要 +1
            else hs[s] = i;		// 没有出现过,是最小下标
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Ypuyu

如果帮助到你,可以请作者喝水~

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

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

打赏作者

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

抵扣说明:

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

余额充值