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)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值