1371.每个元音包含偶数次的最长子字符串

image-20200521155625739

前缀和+状态压缩

代码

/*
 * 1. 记录a e i o u构成整体的状态  范围在00000~11111
 * 2. 如果两次出现了相同的状态,
 *    假设第一次出现在i处,第二次出现的j处,
 *    那么 i+1 ~ j 之间的字符串肯定是满足aeiou出现均为偶数次数的。
 * 3. 因为只有经历了偶数个aeiou,才能回到之前的状态。
 * 4. 为了使得合理的字符串长度最长,需在第一次出现此状态时,就需要记录到下标,然后下一次碰到相同的状态,就  		计算最大长度。
 *
 *14ms
 *时间复杂度 O(n)
 */
class Solution {
    public int findTheLongestSubstring(String s) {
        int n=s.length();
        int[] pos=new int[32];
        Arrays.fill(pos, Integer.MAX_VALUE);
        int ans=0,status=0;
        pos[0]=-1;
        for(int i=0;i<n;i++){
            //更新子串的状态  u o i e a
            char ch=s.charAt(i);
            if(ch=='a'){
                status^=(1);
            }else if(ch=='e'){
                status^=(1<<1);
            }else if(ch=='i'){
                status^=(1<<2);
            }else if(ch=='o'){
                status^=(1<<3);
            }else if(ch=='u'){
                status^=(1<<4);
            }

            if(pos[status]==Integer.MAX_VALUE){
                pos[status]=i;
            }else{
                ans=Math.max(ans, i-pos[status]);
            }
        }
        return ans;
    }
}

思路

  • 将5个元音字母整体出现的奇偶性 视为一个状态,共2^5即32种状态。
  • 如果子串[0,i]与子串[0,j]状态相同,那么子串[i+1,j]的状态一定是00000,理由如下:
    • 假设第一次出现在 i 处,第二次出现的j处,那么 i+1 ~ j 之间的字符串肯定是满足aeiou出现均为偶数次数的。因为只有经历了偶数个aeiou,才能回到之前的状态。
      • 两个数奇偶性相同,相减一定是偶数
      • 两个数奇偶性不同,相减一定时奇数
  • [i+1,j]的长度是 j-(i+1) +1=j-i;即j-i就是符合要求的长度。
  • 为了使得合理的字符串长度最长,只需要记录第一次出现该状态的下标即可。
  • 需要注意状态0首次出现的位置应该设定为-1 原因:
    • 初始化是status已经设置为0,默认已经出现过。
    • pos[0]不设置为-1,下标都是从0开始的,假设第一个字母为 'l' ,与status异或后,status=0符合要求(子串中各元音字符出现次数为0也成立),长度应为1。按照i-pos[status] 公式计算,则计算结果为i+Integer.MAX_VALUE,显然有误。所以pos[0]设置为-1

官方代码

/*
 *14ms
 *时间复杂度 O(n)
 */
class Solution {
    public int findTheLongestSubstring(String s) {
        int n = s.length();
        int[] pos = new int[1 << 5];
        Arrays.fill(pos, -1);
        int ans = 0, status = 0;
        pos[0] = 0;
        for (int i = 0; i < n; i++) {
            char ch = s.charAt(i);
            if (ch == 'a') {
                status ^= (1 << 0);
            } else if (ch == 'e') {
                status ^= (1 << 1);
            } else if (ch == 'i') {
                status ^= (1 << 2);
            } else if (ch == 'o') {
                status ^= (1 << 3);
            } else if (ch == 'u') {
                status ^= (1 << 4);
            }
            if (pos[status] >= 0) {
                ans = Math.max(ans, i + 1 - pos[status]);
            } else {
                pos[status] = i + 1;
            }
        }
        return ans;
    }
}

  • 官方代码中,p[0]=0?计算长度i+1-pos[status] 和 pos[status]=i+1不是特别理解

参考链接:

江户川柯基:简单的思路

官方题解

posted @ 2020-05-21 16:39  YH_Simon  阅读(268)  评论(0编辑  收藏  举报