一、题目描述
给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。
在构造过程中,请注意区分大小写。比如 "Aa"
不能当做一个回文字符串。
注意:
假设字符串的长度不会超过 1010。
示例 1:
输入:
“abccccdd”
输出:
7
解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。
二、解法
本题思路简单,就是统计每个字符出现的次数,并且只能存在一个出现过奇数次的字符,其它出现过奇数次的字符要只能取 n - 1 次。
2.1 自己的常规解法,多次使用 if 判断
class Solution {
public int longestPalindrome(String s) {
int[] num = new int[52]; //严格声明了 52 个空间的数组
int index = 0;
//对数组进行初始化(其实不必)
for(int i = 0; i< num.length; i++) {
num[i] = 0;
}
//统计字母出现的次数
for(char c: s.toCharArray()) {
//第一次使用 if
index = (c - 'a') >= 0 ? (c - 'a') : (c - 'A') + 26;
num[index]++;
}
int flag = 0;
int sum = 0;
//统计回文串长度
for(int i = 0; i < num.length; i++) {
//只能加一个完整的奇数
if((num[i] % 2 > 0) && flag == 0) {//第二次使用 if
sum += num[i];
flag = 1;
} else {
// 如果是偶数,直接相加,如果是奇数,减一再加
//第三次使用if
sum = (num[i] % 2 == 0) ? sum + num[i] : sum + num[i] - 1;
}
}
return sum;
}
}
自己的代码看起来很臃肿啰嗦
2.2 leecode 官方解答
class Solution {
public int longestPalindrome(String s) {
int[] num = new int[58]; //直接声明为长度为 58 的数组,可以省去判断
for(char c: s.toCharArray()) {
num[c - 'A']++; //省去一次 if
}
int sum = 0;
for(int i = 0; i < num.length; i++) {
//直接用 sum % 2 来判断是否有奇数,省去一个变量
if(num[i] % 2 > 0 && sum % 2 == 0) {
sum += num[i];
} else {
//骚操作,直接就省去了判断是否为奇数了,记住这种操作!!!
//又省去一次 if
sum += num[i] / 2 * 2;
}
}
return sum;
}
}
3.3 评论区大神解答
class Solution {
public int longestPalindrome(String s) {
// 找出可以构成最长回文串的长度
int[] arr = new int[58];
for(char c : s.toCharArray()) {
arr[c]++;
}
int count = 0;
for (int i : arr) {
count += (i % 2); //1. 统计奇数出现的次数
}
return count == 0 ? s.length() : (s.length() - count + 1);//2.出现多少个奇数,就用字符串的总长度减这个值,意思是把它们都记录成偶数,然后再加 1,因为可以有一次shi'yo
//1 和 2 结合起来是真的骚
}
}