Leetcode. 1371 每個元音包含偶數次的最長字符串

Leetcode. 1371 每個元音包含偶數次的最長字符串

在這裏插入圖片描述
解題思路
對於代碼中一些變量的解釋,這裏由於只考慮每個元音奇偶次數,因此考慮用二進制來記錄;

  • 定義特徵,aeiou分別對應二進制00001,00010,00100,01000,10000
  • 其中0表示對應元音出現了偶數次數,1表示奇數

從左往右遍歷字符串,不斷更新dp;

  • dp[pattern]的作用是用來記錄當前索引值下對應的元音奇偶次數組合特徵;
    例如:如果pattern爲10,也就是對應二進制 01010,dp[pattern] = 8的意思爲,當索引值爲8的時候,e和o都出現了奇數次,其它元音爲偶數次。

如何找到符合條件最大長度?

  • 根據異或運算規律,異或本身爲0,所以當重複出現偶數次,對應位變爲0,否則爲1

  • 由這個規律可以斷定,當再次出現這個pattern的時候,一定出現了偶數次

  • 爲了方便解釋,pattern如下用二進制表示: 例如,pattern的值變化爲 31–>30–>28–>29–>31
    對應的二進制位[11111]–>[11110]–>[11100]–>[11101]–>[11111] 一個合理的字符串變化:
    ‘aeiou’ --> ‘aeioua’–>‘aeiouae’–>‘aeiouaea’–>‘aeiouaeae’,由此可見,從’aeiou’到’aeiouaeae’這個過程中,多餘出來的‘aeae’爲符合條件的字符串。 所以,在這個過程中,不管中間發生了什麼樣的變化,這兩個狀態之間對應的元音爲偶數,也就是一定符合題意的字符串 因此,不斷更新res,來獲得最大字符串長度

代碼步驟解釋

  • 首先初始化dp長度爲32,對應了5個元音每個次數或奇或偶一共32種狀態
  • 異或運算部分: 遍歷字符串,從起始pattern,也就是0開始,不斷根據對應情況做異或運算
  • 如果出現的是輔音,不進行異或運算
  • 如果出現的是元音,根據元音種類分別對應做異或運算
  • 答案更新: 如果當前的pattern沒有出現過,那麼以這個pattern爲鍵,記錄下當前位置,也就是索引的位置
    如果出現過,那麼更新目標長度:

舉個例子,s='leetcodeo’

  • dp[0]=-1,爲了計算長度方便定義,或者理解爲,開始計算前,參照點在第一個字符之前,也就是-1的位置
  • i=0,l不是元音,pattern不變,
  • i=1,e是元音,pattern變化,由0變爲2,二進制下爲 [00010] dp對應當前pattern對應索引更新爲1
  • i=2,e是元音,pattern變化,由2變爲0,二進制下爲 [00000] 即初始狀態,更新res爲 2-(-1) = 3
  • i=3,t不是元音,pattern不變,res更新爲 3-(-1) = 4
  • i=4,c不是元音,pattern不變,res更新爲 4-(-1) = 5
  • i=5,o是元音,pattern變化,由0變爲8,二進制下爲[01000],dp對應當前pattern對應索引更新爲5
  • i=6,d不是元音,pattern不變,對應cur_len爲 6-5=1,沒有5大,所以當前res還是5
  • i=7,e是元音,pattern變化,由8變爲10,二進制下爲[01010],dp對應當前pattern對應索引更新爲7
  • i=8,o是元音,pattern變化,由10變爲2,二進制下爲[00010],由於這個pattern在i=1出現過,所以用這個對應的i來更新cur_len
    = i-dp[pattern] = 8-1 = 7, 同時res更新到7 遍歷結束,結果爲7
class Solution:
    def findTheLongestSubstring(self, s: str) -> int:
        dp = [-float('inf')]*32
        dp[0] = -1
        pattern = 0
        res = 0
        for i in range(len(s)):
            if s[i] == 'a':
                pattern^= (1<<0)
            elif s[i] == 'e':
                pattern^= (1<<1)
            elif s[i] == 'i':
                pattern^= (1<<2)
            elif s[i] == 'o':
                pattern^= (1<<3)
            elif s[i] == 'u':
                pattern^= (1<<4)
            if dp[pattern] != -float('inf'):
                cur_len = i-dp[pattern]
                res = max(res,cur_len)
            else:
                dp[pattern] = i
        return res

作者:will_never_die
鏈接:https://leetcode-cn.com/problems/find-the-longest-substring-containing-vowels-in-even-counts/solution/xiang-xi-jie-shi-by-will_never_die/
來源:力扣(LeetCode)

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