题目:
给定一个包含大写字母和小写字母的字符串,找到通过这些字母构造成的最长的回文串。
在构造过程中,请注意区分大小写。比如 “Aa” 不能当做一个回文字符串。
注意:
假设字符串的长度不会超过 1010。
实例1:
输入:
"abccccdd"
输出:
7
解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。
思考一:
简单思路,字符成对出现,将字符依次放入到list中,发现list中有该元素,移除并给当前回文串长度+2,最后查看list中是否还有值,有回文串长度为count+1,没有则是count。
import java.util.ArrayList;
import java.util.List;
class Solution {
public static int longestPalindrome(String s) {
char ch[] = s.toCharArray();
List<Character> list = new ArrayList<>();
int count = 0 ;
for (int i = 0; i < ch.length; i++) {
if(list.contains(ch[i])){
remove(list,ch[i]);
count = count + 2;
}else {
list.add(ch[i]);
}
}
if(list.isEmpty()){
return count;
}
return count+1;
}
public static void remove(List<Character> list, Character target){
for(int i = list.size() - 1; i >= 0; i--){
Character item = list.get(i);
if(target.equals(item)){
list.remove(item);
}
}
}
}
虽然运行通过了,但是结果不是那么的完美
执行用时 :11 ms, 在所有 Java 提交中击败了19.96%的用户
内存消耗 :37.6 MB, 在所有 Java 提交中击败了5.25%的用户
对此进行进一步的优化。
思考二:
使用map的特性
import java.util.HashMap;
import java.util.Map;
class Solution {
public static int longestPalindrome(String s) {
char ch[] = s.toCharArray();
Map<Character,Integer> map = new HashMap<>();
int count = 0;
for (int i = 0; i < ch.length; i++) {
if(map.containsKey(ch[i])){
map.remove(ch[i]);
count += 2;
}else {
map.put(ch[i],1);
}
}
if(!map.isEmpty()){
return count+1;
}
return count;
}
}
执行用时 :7 ms, 在所有 Java 提交中击败了35.71%的用户
内存消耗 :38.4 MB, 在所有 Java 提交中击败了5.25%的用户
除了执行耗时进行了稍微提升之外没有其他的提升。
思考三:
以上两个方法都是都是统计对称字符的个数来计算回文串的长度,添加和移除操作难免会有时间复杂度的提升以及内存消耗的提示。
‘A’ - ‘A’ = 0
‘z’ - ‘A’ = 57
根据字符这一个特性,我们可以建立一个长度为58的数组,用下标的形式对应每一个字符。
class Solution {
public int longestPalindrome(String s) {
int[] chs = new int[58];
for (int i = 0; i < s.length(); i++) {
chs[s.charAt(i) - 'A']++;
}
int count = 0;
for (int ch : chs) {
count += (ch / 2) * 2;
}
if (count < s.length()) {
count ++;
}
return count;
}
}
执行用时 :4 ms, 在所有 Java 提交中击败了42.93%的用户
内存消耗 :37.5 MB, 在所有 Java 提交中击败了5.25%的用户
看到这个结果是有点不满意的,没有啥新的想法,看看代码怎么优化吧
class Solution {
public int longestPalindrome(String s) {
int[] chs = new int[58];
for (int i = 0; i < s.length(); i++) {
chs[s.charAt(i) - 'A']++;
}
int count = 0;
for (int ch : chs) {
count += (ch/2)*2;
}
return count<s.length()?count+1:count;
}
}
果然,对代码进行了简单的优化,结果是不同的
执行用时 :2 ms, 在所有 Java 提交中击败了76.48%的用户
内存消耗 :37.7 MB, 在所有 Java 提交中击败了5.25%的用户