![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/cab5d1a48b8dfd557362c10ffc3a16c4.png)
- 我们来看一个字符串abccccddd可以组成的所有回文串,dccaccd,cdcacdc,ccdadcc,dccbccd,cdcbcdc,ccdbdcc,ccdddcc,cdcdcdc,dccdccd
- 你会发现,中间位置的字符,是出现奇数次的字符,而且如果有多个出现奇数次的,例如这里出现奇数次的字符有a,b和d。那么只能选一个作为中间的
- 而对于奇数次的字符
出现一次
的,它只能作为回文串中间
字符- 出现
3次及以上
的,比如上面例子中的d,它可以分一个出来做中间的,其余偶数个放到两边。也可以不分一个出来,仅仅去掉一个
,剩余的偶数个放两边
。
- 而对于偶数次的字符
想要组成最长情况下,必须全放两边。
- 因此,我们可以得到这样一个公式,回文和=偶数和+奇数减1后之和+1,其中+1是回文串中间的那个。奇数减一后之和是因为:除了中间那个+1的,其余字符都必须偶数个。
回文串长度 = 出现偶数次的字符个数 + 出现奇数次(>=3)-1 + 1(放到中间的字符,也就是出现奇数次(1次或3次以上)的,挑一个放到中间)
- 而对于字符出现次数,可以使用hash表统计出现次数。但是题目给的字符范围比较小,只包含大小写字母,所以可以用数组来代替hash表,使用ASCII码最多只需128个空间,就可以代表所有情况。
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/b4e07a34a0db4ec91bf6e979b3862e64.png)
class Solution {
public int longestPalindrome(String s) {
char[] ch=s.toCharArray();
int count[]=new int[128];
for(int i=0;i<ch.length;i++){
count[ch[i]]++;
}
int ans=0;
int js = 0;
for(int i=0;i<128;i++){
if(count[i]%2==0){
ans+=count[i];
}else{
js=1;
if(count[i]>=3){
ans+=count[i]-1;
}
}
}
return ans+js;
}
}