LeetCode1371.每个元音包括偶数次的最长子字符串
题目
分析
错误示范:
首先我先想到的思路就是先把整个字符串遍历一遍,找出所有的元音字母的奇偶数,然后分别从首尾进行遍历删除元素为奇数的元素,但是会造成把原本是偶数对的元音给删成奇数对。所以不行
正解:
- 首先对于五个元音的处理,因为每个元音的奇偶数只有两种状态,要么奇要么偶,所以可以使用01来进行区分,然后一共五位,所以维护一个五位数的二进制数来表示每个元素从头到现在的五个元音的奇偶个数。其中0表示出现了偶数次数,1表示奇数次数。
- 然后维护一个长度为32的数组(元音状态一共有32种),然后每当第一次出现一种新的元音状态的情况,就把当前的位置记录到这个数组中,方便后面如果出现这种同样的元音情况,就可以直接计算出当前位置到第一个位置的长度,即为一个符合标准的子串。
- 然后更新最大的长度,最后返回即可
代码实现
public static int findTheLongestSubstring(String s) {
int len=s.length();
// 创建数组,用来记录这种情况的元音第一次出现的位置
int[] pos=new int[1<<5];
// 先全部置位-1
Arrays.fill(pos,-1);
// ans 记录暂时最长的子串,status标志元音情况
int ans=0,status=0;
// 初始0位置的元素
pos[0]=0;
for(int i=0;i<len;i++){
char ch=s.charAt(i);
// 进行遍历改变state的值
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);
}
// 如果这个元音的值不是-1说明前面有这种情况的元音,就进行一次计算获得暂时的最大值
if(pos[status]>=0){
ans=Math.max(ans,i-pos[status]+1);
}else {
// 不是的话,说明第一次出现这种情况,将第一次的位置记录到pos数组中
pos[status]=i+1;
}
}
return ans;
}