辣雞演算法(五) 字首和 雜湊表優化

2021-10-06 08:13:07 字數 2907 閱讀 5874

這兩天做leetcode,總是做到「字首和」相關的題目,發現了新大陸,在此記錄一下這個東西。

什麼是字首和?

對乙個長度為n的序列nums,將它前i個值求和,得到乙個大小為n的pre陣列,這個陣列記錄的就是字首和。

上面這個定義是我自己寫的,顯然,這個定義是狹義的。從廣義上來講,將序列的前i個值進行任意的函式操作都可以看做是字首和。

記上面提到的函式為int f(vector& pre, int i),則pre[i]=f(i)。

對於將前i個值求和的做法,f函式如下所示:

int f(vector& pre, int i)
字首和有什麼用?求乙個長度為n的序列的區間[j+1, i]的某一性質時,通過pre[i]-pre[j]可以以o(1)的時間複雜度判斷這個區間是否具有這一性質。顯然,這裡的pre[i]-pre[j]也是狹義的。廣義上來講,凡是以pre[i]和pre[j]為引數,以o(1)時間複雜度得出判斷結果的函式都可以。

記上面提到的函式為bool g(vector& pre, int j, int i)。

比如,要求區間[i+1, j]間所有元素的和為k,則g函式如下所示:

bool g(vector& pre, int j, int i)
什麼時候用字首和?當需要大量判斷某些區間的某一性質時使用。比如找出陣列nums中滿足某一性質的區間的個數,比如找出陣列中最長的滿足某一性質的區間,這些區間有o(

雜湊表優化

優化條件:能找到 i 和 j 相關的恒等式pre[j]=h(i)。比如上述的pre[i]-pre[j] == k對應的恒等式為pre[j]=h(i)=pre[i]-k。只有這個等式成立才說明區間[j+1, i]的某一性質。

優化方法:計算pre[j]並放入雜湊表,在計算pre[i]後利用恒等式計算h(i),然後將h(i)和雜湊表中資料比對,如果雜湊表中有則說明區間[j+1, i]的某一性質。

優化結果:將時間複雜度降低o(n)

題目舉例

leetcode 560題:

題目:給定乙個整數陣列和乙個整數k,你需要找到該陣列中和為k的連續的子陣列的個數。

**:

class solution 

return count;}};

pre[i]記錄字首陣列的和。pre[i]計算公式為pre[i]=pre[i−1]+nums[i]。

恒等式為pre[j]==pre[i]−k。

mp[data]記錄的是字首和為data的字首個數。

需要注意的是,從左往右邊更新邊計算的時候已經保證了mp[pre[i]−k] 裡記錄的 pre[j] 的下標範圍是 0≤j≤i 。同時,由於pre[i] 的計算只與前一項的答案有關,因此我們可以不用建立 pre 陣列,直接用 pre 變數來記錄 pre[i−1] 的答案即可。

leetcode 1248題:

題目:

給你乙個整數陣列 nums 和乙個整數 k。

如果某個 連續 子陣列中恰好有 k 個奇數數字,我們就認為這個子陣列是「優美子陣列」。

請返回這個陣列中「優美子陣列」的數目。

**:

class solution 

return ans;}};

pre[i]記錄字首陣列的奇數的個數。pre[i]計算公式為pre[i]=pre[i−1]+(nums[i]&1)。

恒等式為pre[j]==pre[i]−k。

**中的cnt陣列取代了雜湊表,效果一樣。cnt[data]記錄字首陣列中奇數個數為data的字首個數。

需要注意的是,從左往右邊更新邊計算的時候已經保證了cnt[pre[i]−k] 裡記錄的pre[j] 的下標範圍是 0≤j≤i 。同時,由於pre[i] 的計算只與前一項的答案有關,因此我們可以不用建立pre 陣列,直接用odd 變數來記錄 pre[i−1] 的答案即可。

leetcode 1248題:

題目:

給你乙個字串s,請你返回滿足以下條件的最長子字串的長度:每個母音字母,即 'a','e','i','o','u' ,在子字串中都恰好出現了偶數次。

**:

class solution  else if (s[i] == 'e')  else if (s[i] == 'i')  else if (s[i] == 'o')  else if (s[i] == 'u') 

if (~pos[status]) else

}return ans;}};

pre[i][k] 表示在字串前 i 個字元中,第 k 個母音字母一共出現的奇偶性。pre[i][k]的計算公式為pre[i][k]=pre[i-1][k]+is_kth_vowel(s[i])。

接著將pre[i][k]壓縮到乙個5位的二進位制數中,表示前i個字元中個母音字母的奇偶性,記為pre[i]。同前面題目的道理,由於pre[i] 的計算只與前一項的答案有關,因此我們可以不用建立pre 陣列,直接用status 變數來記錄 pre[i−1] 的答案即可。

恒等式為pre[j]==pre[i]。

**中pos陣列取代了雜湊表,效果一樣。pos[data]記錄了字首陣列中最早乙個母音字母奇偶性為data的字首位置。

ps:暫時就碰到三道用字首和與雜湊表做的題目,啃懂這三道,其他題目應該也差不多了吧。

字首和與雜湊表

字首和解法 class solution return count 另解 class solution return flag 雜湊表與unordered map class solution return count unordered map可以看作讀取更快的陣列 number x 的值為num...

和為K的子陣列 字首和 雜湊表

給定乙個整數陣列和乙個整數k,你需要找到該陣列中和為k的連續的子陣列的個數。示例 1 輸入 nums 1,1,1 k 2 輸出 2 1,1 與 1,1 為兩種不同的情況。public int subarraysum int nums,int k mp.put pre,mp.getordefault ...

演算法函式 左神演算法基礎 雜湊函式和雜湊表

筆者在讀研剛開始的時候,偶爾看面經,有這樣乙個問題 只用2gb內存在20億個整數中找到出現次數最多的數,當時的我一臉懵逼,怎麼去思考,20億個數?what the 但是,看完今天的文章,你或許就會覺得原來也不過如此啊!其核心就是雜湊函式和雜湊表的應用!雜湊函式又稱為雜湊函式,就是把任意長度的輸入 又...