title: 最长回文串的直球解法
date: 2020-03-21 07:10:11
tags:
不得不说,你在尝试暴力解法的时候真的很直男
好吧,先把题目贴出来
给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars。
假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符串),那么我们就认为你掌握了这个单词。
注意:每次拼写时,chars 中的每个字母都只能用一次。
返回词汇表 words 中你掌握的所有单词的 长度之和。
我知道,绝对有人看到这个题目最先想的就是把这个字符串拆掉
没错我也是,嘿嘿(。。)
结果往往是一个百把行的代码还出现了Bug还不知道那里错了,难受 >_<
好吧不废话了,来点实在的
public static void main(String[] args) {
String s = new String();
s = "Bansanana";
//提交算法
final int N = 26;
int[] Capital = new int[N]; //放大写字母
int[] Lower = new int[N]; //放小写字母
char[] Loge = new char[s.length()];
int counst = 0,Fia = 0;
Loge = s.toCharArray(); //拆分字符串
//区分大小写,分开处理
for(int i=0;i<s.length();i++){
if(Loge[i] >= 'A' && Loge[i] <= 'Z')
Capital[Loge[i] - 'A']++; //统计出现次数
if(Loge[i] >= 'a' && Loge[i] <= 'z')
Lower[Loge[i] - 'a']++;
}
//判断字符串的长度,分奇偶情况
if(s.length() % 2 == 0){
//偶数情况
for(int i=0;i<N;i++){
if(Capital[i] >= 2)
counst = counst + Capital[i] / 2; //统计成对的字符
}
for(int i=0;i<N;i++){
if(Lower[i] >= 2)
counst = counst + Lower[i] / 2;
}
//偶数情况下,如果成对的字符数*2和字符串的长度相对,那么这个字符串本身就是最长的回文串
//否则,就说明这个字符串中有至少两个单独字符,随便拿一个出来组成回文串即可
if(counst * 2 == s.length())
Fia = s.length();
else
Fia = counst * 2 + 1;
}
else{
//奇数情况
//这一段的操作和上面一模一样的,可以直接烤过来
for(int i=0;i<N;i++){
if(Capital[i] >= 2)
counst = counst + Capital[i] / 2;
}
for(int i=0;i<N;i++){
if(Lower[i] >= 2)
counst = counst + Lower[i] / 2;
}
//奇数情况从这里开始不同了
//在奇数情况下,至少有一个字符注孤生
//当只有一个单独字符时,说明这个字符串本身就是最长回文串(单独字符做中间字符)
//否则,这个字符串就会有至少三个字符是单独字符,随便抽一个单独字符当中间字符即可构成回文串
if(counst * 2 + 1 == s.length())
Fia = s.length();
else
Fia = counst * 2 + 1;
}
System.out.println("\n");
System.out.println(Fia);
}
}
我知道有很多人被那个超长的例子给拦住了,有相同经历的在心中扣个一OK?
大概解释一下思路
用两个数组分别存储大写字母和小写字母的出现次数,每个字母的出现次数默认为0,如果出现一次就在相应位置上加1
最后在确认长度时,只要将成对的字母提取出来,再根据总长度的奇偶情况判断即可求出题目所求
(具体操作写在代码注释里面)
总之,这个题目并不是要我们去拼合字符串而是需要我们去统计出成对的字符,回文串的长度只是一个顺带的操作
在网上还有很多大佬们写的高度简洁、精简的算法,大家可以去看看(我这个学JAVA还不到一个月的砸砸是着实看不懂)