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

Posted 是七喜呀!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《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;
}

以上是关于《LeetCode之每日一题》:49.连续数组的主要内容,如果未能解决你的问题,请参考以下文章

《LeetCode之每日一题》:48.连续的子数组和

《LeetCode之每日一题》:77.绝对差不超过限制的最长连续子数组

《LeetCode之每日一题》:239.最大连续 1 的个数

《LeetCode之每日一题》:272.最大子数组和

《LeetCode之每日一题》:82.最大连续1的个数 III

《LeetCode之每日一题》:81.最大子序和