一、题目
给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。
在构造过程中,请注意区分大小写。比如 “Aa” 不能当做一个回文字符串。
注意:假设字符串的长度不会超过 1010。
示例 1:
输入:“abccccdd”
输出:7
解释:我们可以构造的最长的回文串是 “dccaccd”, 它的长度是 7。
二、思路
处理只含英文字母的字符串,还是采用经典的方法——统计字母出现的次数。
回文串是正着读和反着读都一样的字符串,关于回文串的中心左右对称。很容易发现,对于长度为偶数的回文串,其所有的字符都出现了偶数次,如 “abccba” ;对于长度为奇数的回文串,只有一个字符出现了奇数次,其余字符都出现偶数次,如 “dccaccd”。我们就可以利用这个特性来做,过程如下:
- 统计给定字符串中各字母出现的次数,结果存于数组 charCount 中;
- 遍历数组 charCount,检查每个字母出现的次数;
- 若某个字母出现了偶数次,则字符串中所有的该字母都可以用于构造回文串;
- 若没有字母出现奇数次,则构造完成,否则要进行下一步的处理;
- 若某个字母出现了奇数次,由于回文串中最多只可能有一个字符出现奇数次,所以,所有奇数次的字母次数减一后用于构造回文串,最后给回文串长度加一即可。
注意两点:
(1)这里的字符串包含大写和小写,而大小写字母在 ASCII 码表中并不是连续的,所以在统计次数时,应创建一个长度为 58 的数组。(也可以创建两个长度为 26 的数组)。
(2)代码中可以设定一个 flag 变量,用于判断是否有出现奇数次的字母。
三、代码
class Solution {
public int longestPalindrome(String s) {
int[] charCount = count(s);
int l = 0;
int flag = 0;
for(int i = 0; i < charCount.length; i++){
if(charCount[i] % 2 == 0){
l += charCount[i];
}
if(charCount[i] % 2 == 1){
l += (charCount[i] - 1);
flag++;
}
}
if(flag > 0)
l += 1;
return l;
}
public int[] count(String s){
int[] countRes = new int[58];
for(int i = 0; i < s.length(); i++){
countRes[(int)(s.charAt(i) - 'A')] += 1;
}
return countRes;
}
}