问题描述
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符
例如mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)
输入
输入描述:
第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
第二行是一个字符串,长度为N.只包含小写字母
输入样例:
5
mamad
输出
输出描述:
如果可能,输出最少的交换次数。
否则输出Impossible
输出样例:
3
HINT:时间限制:1.0s 内存限制:512.0MB
解题思路
首先要判断输入的是不是回文数,就先判断每个字母出现的次数以及奇数字母的个数,若奇数次数的字母个数大于1的话就不能构成回文数,在判断交换次数时还要注意如果是1位或者2位字符串的话就直接返回0,因为1,2位的就是回文数不用交换,接下来就是判断每次首字母在后面出现的次数了,如果首字母只有一次的话就把他放到中间,其余的再进行循环运算,就相当于在中间的两边加字符。
代码
import java.util.Locale;
import java.util.Scanner;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
Scanner scanner=new Scanner(System.in);
int m=scanner.nextInt();
String n=scanner.next();
if (panduan(n)){
System.out.println(cishu(n));
}else {
System.out.println("Impossible");
}
}
public static boolean panduan(String n){
//判断是否构成回文数 就是判断字母出现为奇数次数的个数
boolean panduan=true;
int [] num=new int[26];
int geshu=0;//记录奇数次的个数
for (int i=0;i<n.length();i++){
num[n.charAt(i)-'a']++;//得到每个字母对应的数值
}
//统计奇数次字母出现的个数
for (int i=0;i< num.length;i++){
if (num[i]%2==1){
geshu++;
}
}
if (geshu>1){
panduan=false;//若大于1 则不能形成回文数
}
return panduan;
}
//如果为回文数 则判断交换次数
public static int cishu(String n){
int cishu=0;
if(n.length()==1 || n.length()==2){//只有1位和2位的字符串 就是回文数 返回0次
return 0;
}
cishu=n.lastIndexOf(n.charAt(0));//每次首字母最后出现位置的索引
if (cishu==0){
return n.length()/2 + cishu(n.substring(1,n.length()));//如果首字母只出现了首字母放到中间
//substring的作用为截取第1位到最后一位的字符串。
}else {
StringBuilder stringBuilder=new StringBuilder(n);//如果不为1次的话移动的次数就是 长度-cishu-1 然后再删除计算过的。
stringBuilder.deleteCharAt(cishu);//删除已经计算过的
//deleteCharAt为移除此位置的字符
stringBuilder.deleteCharAt(0);
return n.length()-cishu-1 + cishu(stringBuilder.toString());
}
}
}