leetcode--hash--Contiguous Array

題目描述:Given a binary array, find the maximum length of a contiguous subarray with equal number of 0 and 1.

Note: The length of the given binary array will not exceed 50,000.

思路,參考官網,將數組中的 0 全都轉化爲 -1,然後遍歷數組求和sum:如果遍歷到下標a時的sum=K,繼續遍歷到下標b時的sum還是sum=K,(a<b),那麼可以得出(a~b] 的數組滿足要求。即得出結果是 result = b - a;這是這個算法的數學依據。接下來考慮的是當得出sum之後,如何快速的判斷該sum值有沒有出現過,如果出現過,如何快速的找到該sum值對應的下標值? 

//方法一,用map結構保存sum值和sum值對應的下標,實現快速判斷sum值是否存在。因爲map的底層實現是紅黑樹數據結構,每次 .find 都需要花費 log(n)的時間。在LeetCode上僅僅擊敗了3.66%的碼友. 運行時間約 200 ms

int findMaxLength(vector<int>& nums) {
        int result = 0, sum = 0;
        for (int i = 0; i < nums.size(); i++)
            if (nums[i] == 0) nums[i] = -1;

        map<int, int> m;
        m[0] = -1;  //這個是必須的初始條件。考慮 0,1 的場景
        for (int i = 0; i < nums.size(); i++) {
            sum += nums[i];
            if (m.find(sum) != m.end()){   //注意,找到了重複的sum,只是更新result,並不對m[sum]做更新
                result = max(result, i - m[sum]);
            }else{
                m[sum] = i;  //在相同的幾個sum中,m[sum]總是保存的是最開始的那個下標值
            }
        }
        return result;
}

 

//方法二,直接用數組保存值。雖然花費了更多的空間,但這個方法測試比方法一快一倍!運行時間約 100 ms

int findMaxLength(vector<int>& nums)
{
    int result = 0;
    int sum = 0;

    //初始化數組
    int size = 2*nums.size() + 1;
    vector<int> vec;
    for(int i=0; i<size; ++i)
    {
        vec.push_back(-2);
    }
    vec[0] = -1;  //注意vec[0] = -1 必須初始化爲 -1
    //遍歷數組,記錄當前的數組和sum,查hash表,
    //如果sum對應的值不爲空(-2),那麼sum值出現過,用當前的下標減去sum值對應的下標方式求結果。
    //如果sum對應的值爲空(-2),那麼該值沒有出現過,需要保存當前sum的下標值
    int sumTmp = 0;
    for(int i=0;i<nums.size();++i)
    {
        if(0==nums[i])
        {
            sum -=  1;
        }else{
            sum += 1;
        }
        //哈希轉換,sum<0時取反,在加上vec的size大小(sum爲負值時用vec[n+1~2n])
        if(sum<0){
            sumTmp = (nums.size() - sum);
        }else{
            sumTmp = sum;
        }

        //assert(sumTmp<size);  //證明sumTmp不越界訪問
        if(-2 != vec[sumTmp])  //有記錄則更新結果
        {
            result = max(result, i - vec[sumTmp]);
        }else{  //沒有記錄則更新
            vec[sumTmp] = i;
        }
    }
    return result;
}

 

//第三種解法,需要熟悉C++的map實現的數據結構,map底層實現是紅黑樹,有沒有底層實現是hash的map,實現 .find 方法的Q(1)訪問? 答案是 unordered_map,所以選對工具很重要。該方法兼顧時間和空間效率,實現簡單,難以出錯。在LeetCode上擊敗了 93.84% 的碼友

int findMaxLength(vector<int>& nums) {
        int result = 0, sum = 0;
        for (int i = 0; i < nums.size(); i++)
            if (nums[i] == 0) nums[i] = -1;

        unordered_map<int, int> m;
        m[0] = -1;  //這個是必須的初始條件。考慮 0,1 的場景
        for (int i = 0; i < nums.size(); i++) {
            sum += nums[i];
            if (m.find(sum) != m.end()){   //注意,找到了重複的sum,只是更新result,並不對m[sum]做更新
                result = max(result, i - m[sum]);
            }else{
                m[sum] = i;  //在相同的幾個sum中,m[sum]總是保存的是sum第一次出現的那個下標值
            }
        }
        return result;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章