409.最长回文串
1. 题目描述
题目中转:409.最长回文串
2.详细题解
先厘清回文串的概念,指:左往右读和从右往左读都是一样的字符序列,例如level、noon、racecar、civic和deified等都是回文字符串。
题目已知一些包含大小写字母的字符串,要求使用这些字母组成回文串,并给出能够组成的最长字符串的长度,并且需要区分字母的大小写,一个字母最多只能使用一次。
注意仔细阅读回文串的定义,以及仔细观察回文串组成字符的数量特点,从左往右和从右往左读都是一样的,说明一旦左边有一个字符,那么必然右边有一个相同的字符,因此说明回文字符串中出现的字符的次数一定是偶数的,但有一个例外,那就是最中心位置处的字符可以仅出现一次,即这时回文串的字符长度为奇数,例如level。
因此,根据上述回文串的特点,为了利用已有字符实现最长回文串,则需最大限度的利用所有的字符(若某字符个数为n,如果n为偶数则使用n个,否则使用n-1个,只要为偶数个则一定可以构成回文),但需注意的是,回文串长度为奇数时,中间位置可以出现单独一次的情况,故需判断是否有剩余的字符,若有则可插入中间位置,回文串长度还可+1.
本题仅给出字符串,故首先需统计出各个字符出现的次数,而后即可判断最长的回文串长度(方法一);或者遍历字符的同时判断是否已出现偶数次(2次)即可增加回文长度。
3.代码实现
3.1 Python
class Solution:
def longestPalindrome(self, s: str) -> int:
dicts = Counter(s) # 使用collections.Counter()方法统计各字符出现次数
ans = 0 # 记录回文串长度
centor = 0 # 记录是否出现剩余的单数字符
for _,v in dicts.items():
if not centor and v % 2 == 1: # 记录一次剩余字符即可
centor = 1
ans += v if v % 2 == 0 else v-1 # 如果为偶数则加上相应长度,否则加上减1的长度
return ans + centor
class Solution:
def longestPalindrome(self, s: str) -> int:
char_set = set() # 使用一个集合保存单个字符
ans = 0
for c in s: # 遍历每个字符
if c not in char_set: # 如果字符不存在集合中说明为单个字符
char_set.add(c)
else: # 再次出现此字符,共计2次,可加入回文
ans += 2
char_set.remove(c) # 从集合中移除
return ans if len(char_set) == 0 else ans + 1
3.2 Java
class Solution {
public int longestPalindrome(String s) {
int count[] = new int[123]; // 大小写字母的最大ASCII的编制为122,因此使用一个123大小的整数数组来记录各个字符出现的次数
for (int i=0;i < s.length(); i++){
char c = s.charAt(i);
count[c]++;
}
int ans = 0;
int centor = 0;
for (int v: count){
if (centor == 0 && v % 2 == 1){
centor = 1;
}
ans += v / 2;
}
ans *= 2; //直接只记录了一半长度
return centor==0 ? ans : ans + 1;
}
}
执行用时不必过于纠结,对比可以发现,对于python和java完全相同的编写,java的时间一般是优于python的;至于编写的代码的执行用时击败多少对手,执行用时和网络环境、当前提交代码人数等均有关系,可以尝试完全相同的代码多次执行用时也不是完全相同,只要确保自己代码的算法时间复杂度满足相应要求即可,也可以通过点击分布图查看其它coder的code