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

原题

给你一个字符串 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 只包含小写英文字母。

解法

思想

使用官方题解的前缀和+状态压缩!

这道题不好想,如果用暴力在leetcode绝对超时,可以想到用前缀和的方法。

前缀和怎么做呢?如果要两个字符串的差值(字符串交集)中,a,e,i,o,u全部为偶数,那么根据数学知识,偶数减偶数是偶数,奇数减奇数也是偶数。也就是说两个字符串中的这五个字母出现的奇偶性必须一样!

而五个字母,每个字母出现的次数都可奇可偶,组合出来的情况有很多种,在遍历的时候遇到其中一种奇偶性组合,如何知道最早出现的同一种奇偶性组合出现在哪个位置呢?

这里有一种方法:遍历的时候记录并计算所有字母的个数,然后对每次遍历到的位置,将它的奇偶性组合编码成字符串,例如“奇偶奇偶奇”,代表a,i,u出现奇数个,而e,o出现偶数个。然后就以这个字符串为键,第一次出现的顺序为值存放到哈希表中。后面只要出现相同的奇偶性排列,就把它从哈希表中取出来,就知道最早出现的位置,两个位置一减就是字符串的长度。

但是这种方法需要构造字符串,并且需要记录五种字母出现的个数,十分麻烦,那么可以利用“状态压缩”+“位运算”的方法:将这种奇偶性排列编码成一个五位的二进制位串,例如二进制的"10101",代表a,i,u出现奇数个,而e,o出现偶数个。每一个字母都映射到位串的一个位上,而再出现一个字母的时候,就通过异或运算更改对应位上的值。

例如: "10101" :a,i,u出现奇数个,e,o出现偶数个
(再出现一个i)->"10101"^"100" = "10001",即a,u出现奇数个,e,i,o出现偶数个。

代码

class Solution {
    public int findTheLongestSubstring(String s) {
        int n = s.length();
        int[] pos = new int[1 << 5];
        // 如果是-1,说明还没有出现这种奇偶性排列
        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;
    }
}

原创文章,作者:彭晨涛,如若转载,请注明出处:https://www.codetool.top/article/leetcode1371-%e6%af%8f%e4%b8%aa%e5%85%83%e9%9f%b3%e5%8c%85%e5%90%ab%e5%81%b6%e6%95%b0%e6%ac%a1%e7%9a%84%e6%9c%80%e9%95%bf%e5%ad%90%e5%ad%97%e7%ac%a6%e4%b8%b2/

(0)
彭晨涛彭晨涛管理者
上一篇 2020年5月19日 15:23
下一篇 2020年5月20日

相关推荐

  • leetcode205-同构字符串

    原题 给定两个字符串 s 和 t,判断它们是否是同构的。 如果 s 中的字符可以被替换得到 t ,那么这两个字符串是同构的。 所有出现的字符都必须用另一个字符替换,同时保留字符的顺…

    算法 2019年12月21日
    0220
  • leetcode990-等式方程的可满足性

    原题 给定一个由表示变量之间关系的字符串方程组成的数组,每个字符串方程 equations[i] 的长度为 4,并采用两种不同的形式之一:"a==b" 或 "a!=b"。在这里,a…

    算法 2020年6月8日
    0100
  • leetcode142-环形链表II

    原题 给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始…

    2019年12月14日
    0440
  • leetcode652-寻找重复的子树

    原题 给定一棵二叉树,返回所有重复的子树。对于同一类的重复子树,你只需要返回其中任意一棵的根结点即可。 两棵树重复是指它们具有相同的结构以及相同的结点值。 示例1: 1 / \ 2…

    算法 2019年12月26日
    0310
  • leetcode264-丑数II

    原题 编写一个程序,找出第 n 个丑数。 丑数就是只包含质因数 2, 3, 5 的正整数。 示例: 输入: n = 10 输出: 12 解释: 1, 2, 3, 4, 5, 6, …

    算法 2020年2月10日
    0190
  • leetcode162-寻找峰值

    原题 峰值元素是指其值大于左右相邻值的元素。 给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。 数组可能包含多个峰值,在这种情况…

    算法 2020年1月3日
    060
  • leetcode1248-统计「优美子数组」

    原题 给你一个整数数组 nums 和一个整数 k。 如果某个 连续 子数组中恰好有 k 个奇数数字,我们就认为这个子数组是「优美子数组」。 请返回这个数组中「优美子数组」的数目。 …

    算法 2020年4月21日
    0320
  • leetcode34--在排序数组中查找元素的第一个和最后一个位置

    原题 给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。 你的算法时间复杂度必须是 O(log n) 级别。 如果数…

    算法 2020年1月3日
    0150
  • leetcode611-有效三角形的个数

    原题 给定一个包含非负整数的数组,你的任务是统计其中可以组成三角形三条边的三元组个数。 示例1: 输入: [2,2,3,4] 输出: 3 解释: 有效的组合是: 2,3,4 (使用…

    2020年2月8日
    070
  • leetcode64-最小路径和

    原题 给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。 说明: 每次只能向下或者向右移动一步。 示例: 输入: [ [1,3…

    算法 2020年2月24日
    0100

发表回复

登录后才能评论