前缀和(7)_连续数组

个人主页:C++忠实粉丝
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 C++忠实粉丝 原创

前缀和(7)_连续数组

收录于专栏【经典算法练习
本专栏旨在分享学习算法的一点学习笔记,欢迎大家在评论区交流讨论💌

目录

1. 题目链接 :

2. 题目描述 :

3. 解法(一维前缀和) :

    算法思路 :

   示例说明:

    代码展示 :

    结果分析:

 


1. 题目链接 :

OJ链接: 连续数组

2. 题目描述 :

给定一个二进制数组 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 <= 105
  • nums[i] 不是 0 就是 1

3. 解法(一维前缀和) :

    算法思路 :

转换 0 和 1:

将 0 视作 - 1,而 1 保持不变。这意味着在计算前缀和时,0 会减少总和。
这样,当某段区间内的 0 和 1 数量相同时,前缀和将回到相同的值。

计算前缀和:

遍历数组时,维护一个变量 sum 用来表示当前的前缀和。
如果在某个位置的 sum 值与之前某个位置的 sum 值相同,说明从这两个位置之间的元素(即子数组)中,0 和 1 的数量相等。

使用哈希表记录前缀和的索引:

使用一个哈希表 dp 来存储每个前缀和第一次出现的索引。
初始化 dp[0] = -1,表示前缀和为 0 的情况下,虚拟的索引是 - 1,这有助于处理从数组起始位置开始的有效子数组。

判断条件:

在遍历数组时,每当计算新的前缀和 sum:
        如果 sum 已经在 dp 中存在(即 dp.count(sum) 为真),这意味着从 dp[sum] + 1 到当前索引 i 的这段区间中,0 和 1 的数量相等。
        通过计算当前索引 i 与 dp[sum] 的差值得到这段子数组的长度:i - dp[sum]。

   示例说明:

假设有一个数组 nums = [0, 1, 0, 1],我们可以按以下步骤分析前缀和的变化:

初始状态:

dp = { 0: -1 }
sum = 0
ret = 0

遍历数组:

i = 0, nums[0] = 0:
        sum = 0 + (-1) = -1
        dp[-1] 不存在,所以将 dp[-1] = 0。
i = 1, nums[1] = 1 :
    sum = -1 + 1 = 0
    dp[0] 已存在,表示从 dp[0] + 1 到 i 的子数组有相同数量的 0 和 1,长度为 1 - (-1) = 2,更新 ret = 2。

 i = 2, nums[2] = 0 :
    sum = 0 + (-1) = -1
    dp[-1] 已存在,长度为 2 - 0 = 2,ret 不变。

i = 3, nums[3] = 1 :
    sum = -1 + 1 = 0
    dp[0] 已存在,长度为 3 - (-1) = 4,更新 ret = 4。

    代码展示 :

class Solution {
public:
    int findMaxLength(vector<int>& nums) {
        unordered_map<int, int> dp;
        dp[0] = -1;
        int sum = 0, ret = 0;
        for(int i = 0; i < nums.size(); i++)
        {
            sum += nums[i] == 0 ? -1 : 1;
            if(dp.count(sum)) ret = max(ret, i - dp[sum]);
            else dp[sum] = i;
        } 
        return ret;
    }
};

 

    结果分析:

时间复杂度和空间复杂度
时间复杂度 :O(n),其中n 是数组的长度。我们只遍历数组一次。
空间复杂度 :O(n),在最坏情况下,哈希表可能存储所有的前缀和。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值