解题思路
“Impossible”情况是:
出现奇数次的字母 多于一个。
如果是奇数: ababc 满足 abade 不满足
如果是偶数: abab 满足 ab 不满足
技巧
“那如何统计字母出现的次数呢?”
a[Str.charAt(i)-'a']++
将字符转化为数字,减去字母‘a’的值正好为其对应的数组下标值。
“能构成回文数”:
递归思路。
- 判断长度1或者为2时,直接返回0次。
if(string.length() == 1 || string.length() == 2){
return 0;
}
- 与首字母匹配的从后往前的下标值,将值存入 temp中。这里用到了str.LastIndexOf(charAt(0))
又分两种情况
1)temp = 0 时,说明首字母只出现了一次,则需要把这个字母移到中间,则是len/2次。
if(temp == 0){
return string.length()/2 + getResult(string.substring(1,string.length()));
}
2)temp != 0 时,说明这个首字母出现了不止一次,则其需要移动的次数是 len - temp - 1 次,然后再删除计算过的。 这里又用到了StringBuilder 这个类中的 deleteCharAt(0) 函数。
else{
StringBuilder stringBuilder = new StringBuilder(string);
stringBuilder.deleteCharAt(temp);
stringBuilder.deleteCharAt(0);
return string.length()-temp-1+getResult(stringBuilder.toString());
}
完整代码
package 完美的代价_求成回文的最小次;
import java.util.Scanner;
public class Main_my {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
String string = scanner.next();
if(IsPossible(string)){
System.out.println(getResult(string));
}else{
System.out.println("Impossible");
}
}
//判断能否构成回文数
public static boolean IsPossible(String string){
boolean ans = true;
int[] a = new int[26];
int count = 0; //这个用于计数奇数次的个数
//把每一个字母出现的次数存入数组中。
//这里的巧妙之处在于这个正好可以 string.charAt(i)-'a' 得到对应字母的下标值。
for(int i = 0; i < string.length(); i++){
a[string.charAt(i)-'a']++;
}
//统计出现奇数次字母的个数
for(int i = 0 ;i < a.length; i++){
if(a[i]%2==1){
count++;
}
}
//如果奇数次的字母个数大于一个的话,则不能构成回文数
if(count>1){
ans = false;
}
return ans;
}
//如果能构成回文数,在此基础上,判断需要移动几次。
public static int getResult(String string){
int temp = 0;
if(string.length() == 1 || string.length() == 2){
return 0;
}
temp = string.lastIndexOf(string.charAt(0));
if(temp == 0){
return string.length()/2 + getResult(string.substring(1,string.length()));
}else{
StringBuilder stringBuilder = new StringBuilder(string);
stringBuilder.deleteCharAt(temp);
stringBuilder.deleteCharAt(0);
return string.length()-temp-1+getResult(stringBuilder.toString());
}
}
}