试题 基础练习 完美的代价
题目
问题描述
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符
例如mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)
输入格式
第一行是一个整数N,表示接下来的字符串的长度(N <= 8000)
第二行是一个字符串,长度为N.只包含小写字母
输出格式
如果可能,输出最少的交换次数。
否则输出Impossible
样例输入
5
mamad
样例输出
3
问题分析
字符串的长度有奇数和偶数两种可能。
Impossible有两种可能:
1,字符串长度为奇数,且至少含有两个只出现一次的字符
2,字符串长度为偶数,且含有一个或多个只出现一次的字符
解决思路
-》从字符数组的第一个位置开始,从后向前遍历寻找与其相同的字符。
-》》》如果出现该字符,且并不是本身位置,那么将字符移到回文相对应的位置。
-》》》如果找到该字符,且为本身位置,那么这个字符只出现了一次
-》》》》》如若数组长度为偶数或曾经出现过单个字符,则打印impossible
-》》》》》如若数组长度为奇数,记录曾出现过单个字符,并且该字符移向字符数组中间
Java代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n;
n = scanner.nextInt();
String str;
str = scanner.next();
scanner.close();
char[] chs = str.toCharArray();
int j = n-1,count=0,flag=0;
for(int i=0; i < j; i++) {
for(int k=j; k >= i; k--) {
if(i==k) {
if(n%2==0 || flag==1) {
System.out.println("Impossible");
return ;
}
flag = 1;
count += n / 2 - i;
}
else if(chs[i] == chs[k]){
for(int l = k; l < j; l++){
swap(chs,l,l+1);
count++;//统计交换次数
}
j--;
break;
}
}
}
System.out.println(count);
}
private static void swap(char chs[],int i,int j) {
char temp = chs[i];
chs[i] = chs[j];
chs[j] = temp;
}
}