JavaScript:leecode_1371. 每個元音包含偶數次的最長子字符串(前綴和)

題目說明

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

 

示例 1:

輸入:s = "eleetminicoworoep"
輸出:13
解釋:最長子字符串是 "leetminicowor" ,它包含 e,i,o 各 2 個,以及 0 個 a,u 。
示例 2:

輸入:s = "leetcodeisgreat"
輸出:5
解釋:最長子字符串是 "leetc" ,其中包含 2 個 e 。
示例 3:

輸入:s = "bcbcbc"
輸出:6
解釋:這個示例中,字符串 "bcbcbc" 本身就是最長的,因爲所有的元音 a,e,i,o,u 都出現了 0 次。
 

提示:

1 <= s.length <= 5 x 10^5
s 只包含小寫英文字母。

解題思路一

  1. 首先要理解這個題。這道題明顯還是跟前綴有關係的東西,毫無疑問肯定又需要用到動態規劃保存狀態。
  2. 我們先來看子字符串中的各元音字母的個數,題目呢,要求的是偶數次,那麼我們的a,e,i,o,u的出現次數是不是可以轉化爲出現次數奇偶性呢?即
    1. nums % 2 === 1 是奇數次
    2. nums % 2 === 0 是偶數次
  3. 那麼我們的a,e,i,o,u的各自狀態就只有兩種情況啦,0 or 1,例如
    'a': 0,
    'e': 0,
    'o': 1,
    'i': 0,
    'u': 0
    
    那我們現在用二進制來表示一下它:00100, 那麼類似於這樣的表示有幾種情況呢? 2 x 2 x 2 x 2 x 2 = 32僅僅只有32種情況,就可以完全表示元音字母的所有狀態了。那麼我們聲明一個長度爲32status數組,值都初始化爲-1
  4. 按照正常思維,符合條件的情況有兩種子字符串,一是從頭開始的,一個是從中間開始的。
    1. 從頭開始的很容易理解(假設首位下標爲0,i),只要從0到i,狀態爲00000就可以了。代表都是偶數次出現。
    2. 從中間開始的話(假設首位下標爲j,i),是從j到i這個子字符串的狀態爲00000
    3. 那什麼情況下子字符串的狀態可以是00000呢? 那當然是i,j各自的狀態一致的時候,因爲同狀態互減纔會爲0,例如01000 - 01000 = 00000
    4. so,01000在字串中是會出現多次的,因爲2%2 == 0, 4%2===0狀態也是會重複的,所以我們想求出這個狀態之間的最大間距,就要記錄該狀態最早出現的下標。
  5. 好了,理解了這個狀態之後,我們明確了我們要記錄的值,記錄該位置的狀態下的最早下標。
  6. 我們是不是可以記錄一下,從第1個字母開始到第i個字母之間的各元音狀態呢?
  7. 例如:"eleetminicoworoep" 對應的狀態數組[01000,01000,00000,01000,01000,01000,01100...]
  8. i 爲 0,1,3,4,5 的時候狀態都一致,那麼我們只需要記錄status[8] = 0,取最小值即可。
  9. 所以status數組記錄的是32種狀態各自在字符串中最早出現的下標
  10. 最後我們遍歷字符串,求出每一位的狀態key(例如01000) ,根據這個key和下標i,我們去status裏面找key最小下標status[key],然後用i - status[key]求出距離長度。若status[key]爲-1,則將下標i賦值給status[key] = i

代碼實現一

/**
 * @param {string} s
 * @return {number}
 */
var findTheLongestSubstring = function(s) {
    let hash = {
        'a': 0,
        'e': 0,
        'o': 0,
        'i': 0,
        'u': 0
    }
    let status = new Array(32).fill(-1);
    status[0] = 0;
    let max = 0;
     for (let i = 0; i < s.length; i++) {
        let key = 0;
        hash[s.charAt(i)] !== undefined ? hash[s.charAt(i)] = (hash[s.charAt(i)] + 1) % 2 : '';
        key += hash['a'] + (hash['e'] << 1) + (hash['i'] << 2) + (hash['o'] << 3) + (hash['u'] << 4)
        if (status[key] === -1) {
            status[key] = i + 1;
        } else {
            max = Math.max(max, i + 1 - status[key])
        }
    }
    return max;
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章