LeetCode 1371. 每个元音包含偶数次的最长子字符串
https://leetcode-cn.com/problems/find-the-longest-substring-containing-vowels-in-even-counts/
这个是今天的每日一题,菜鸡的我又没有作出来 QAQ
只能乖乖去看花花酱的视频了,贴一下代码吧
public int findTheLongestSubstring(String s) { char[] vol = new char[]{'a','e','i','o','u'}; int[] list = new int[32]; Arrays.fill(list,Integer.MAX_VALUE); list[0] = -1; int max = 0; int state = 0; for(int i = 0;i < s.length(); i++){ for(int j = 0; j < vol.length; j++){ if(s.charAt(i) == vol[j]){ state ^= 1<<j; } } if(list[state] == Integer.MAX_VALUE){ list[state] = i; } max = Math.max(max,i-list[state]); } return max; }
这个题考的知识点真的好多好多,首先有前缀和,类似15号的每日一题LeetCode 560,还有就是状态压缩,类似于老鼠检验毒药问要多少只老鼠的题目。
首先我们用一个char数组记录下元音字母。另外我们需要一个32位的数组来记录每个状态的第一次出现的位置,因为状态压缩后,一共有5位二进制位,2^5=32.
首先我们将第一个状态位置-1,因为全部的元音为偶数情况有可能是整个字符串。
然后看循环,第一层循环是遍历整个字符串,因为这个字符串规模很大,最多只支持我们遍历一次。
第二层循环是判断当前字符是否为其中的一个元音,如果是的话就将状态位与1<<j,即00000中的第j位被置为1,然后再与state进行异或,将状态进行转换。
然后如果当前状态的第一次出现的位置为Integer.MAX_VALUE的话,就表示这个状态从来没出现过,这里是第一次出现,将i赋予它。
然后就是比较max和i-list[state]这个哪个更长,记录下来最长的那个即可。
这里贴一下花花酱的视频,可能比我这个讲解会更好理解。https://www.bilibili.com/video/BV1CE411K7hb