《LeetCode之每日一题》:49.连续数组

连续数组


题目链接: 连续数组

有关题目

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

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

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

1 <= nums.length <= 10^5
nums[i] 不是 0 就是 1

题解

前缀和+哈希表

思路:
优化一:如果答案非 0,那么子数组长度必然为偶数,且长度至少为 2
理解1.
转换,1的数量和0的数量相等,即1的数量减去0的数量为零
我们将数组的中的0视作-1,那么我们求解的题目就变为了
求最长的连续子数组,其元素和为0
理解2.
前缀的思想在于,利用不同段的计数作差来得出中间连续子数组的存在

因为我们需要知道的是存在性,所以我们只需要用哈希维护计数的存在即可

参考官方题解
代码一:

class Solution {
public:
    int findMaxLength(vector<int>& nums) {
        unordered_map<int,int> mp;
        int counter = 0;
        int maxLength = 0;//最大长度
        mp[counter] = -1;//规定空串的前缀结束的下标为-1,空的前缀为元素和为0;
        for (int i = 0; i < nums.size(); i++)
        {
            //为0counter--,为1counter++
            if (nums[i] == 1)
                counter++;
            else
                counter--;

            if (mp.find(counter) != mp.end())
                maxLength = max(maxLength,i - mp[counter]);
            else
                mp[counter] = i;
        }
        return maxLength;
    }
};

在这里插入图片描述
代码二:

class Solution {
public:
    int findMaxLength(vector<int>& nums) {
        unordered_map<int,int> mp;
        int sum = 0, ans = 0;
        mp[sum] = -1;
        for (int i = 0; i < nums.size(); i++)
        {
            sum += nums[i] ? 1 : -1;//这边?:的优先级顺序高于+=所以运算顺序为sum += (num[i] ? 1 :-1)
            auto p = mp.find(sum);//find函数返回的是个地址
            if (p != mp.end())
                ans = max(ans, i - p->second);//根据hash表中的成员列表我们知道,second就是对应前缀和的下标
            else
                mp[sum] = i;
        }
        return ans;
    }
};

代码三:(目前跑不过去)
参考宫水三叶

思路;
如何求得最长一段区间和为 0 的子数组。

同时使用「哈希表」来记录「某个前缀和出现的最小下标」是多少。

再结合「如果答案非 0,子数组长度至少为 2的特性,我们让循环从 2开始。

答案为零返回0
class Solution {
public:
    int findMaxLength(vector<int>& nums) {
        int ans = 0;
        vector<int> sum(nums.size() + 1,0);
        for (int i = 1; i <= nums.size(); i++)
            sum[i] = sum[i - 1] + (nums[i - 1] == 1 ? 1 : -1);
        unordered_map<int,int> mp;
        mp[0] = -1;
        for (int i = 2; i <= nums.size(); i++)
        {
            //同时使用「哈希表」来记录「某个前缀和出现的最小下标」是多少。

//再结合「如果答案非 0,子数组长度至少为 2的特性,我们让循环从 2开始。
            if (mp.find(sum[i]) != mp.end())
                 ans = max(ans,i - mp[sum[i]]);
            if (!mp.count(sum[i - 2]))
                mp[sum[i - 2]] = i - 2;
        }
        return ans;
    }
};

C版本

struct HashTable
{
    int key,value;
    UT_hash_handle hh;
};

int findMaxLength(int* nums, int numsSize){
    int maxLength = 0;
    struct HashTable* hashTable = NULL;
    struct HashTable* tmp = (struct HashTable*)malloc(sizeof(struct HashTable));
    tmp->key = 0, tmp ->value = -1;
    HASH_ADD_INT(hashTable,key,tmp);
    int counter = 0;
    for (int i = 0;i < numsSize; i++)
    {
        if (nums[i] == 1)
            counter++;
        else 
            counter--;
        HASH_FIND_INT(hashTable,&counter,tmp);
        if (tmp != NULL)
            maxLength = fmax(maxLength,i - tmp->value);
        else
        {
            tmp = malloc(sizeof(struct HashTable));//重新开辟空间给tmp
            tmp->key = counter,tmp->value = i;
            HASH_ADD_INT(hashTable,key,tmp);
        }       
    }
    return maxLength;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值