BASIC-19 完美的代价
BASIC-19 完美的代价
题目
资源限制
时间限制:1.0s 内存限制:512.0MB
问题描述
回文串,是一种特殊的字符串,它从左往右读和从右往左读是一样的。小龙龙认为回文串才是完美的。现在给你一个串,它不一定是回文的,请你计算最少的交换次数使得该串变成一个完美的回文串。
交换的定义是:交换两个相邻的字符
例如 mamad
第一次交换 ad : mamda
第二次交换 md : madma
第三次交换 ma : madam (回文!完美!)
输入格式
第一行是一个整数 N,表示接下来的字符串的长度(N <= 8000)
第二行是一个字符串,长度为 N.只包含小写字母
输出格式
如果可能,输出最少的交换次数。否则输出 Impossible
样例输入
5
mamad
样例输出
3
题解
/*
1. 循环,三指针
2. 递归
3. 并查集
*/
import java.util.Scanner;
public class BASIC_19 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
String str = sc.next();
char arr[] = str.toCharArray();
sc.close();
//回文
if (palindrome(arr, 0, n - 1)) {
System.out.println(cnt);
} else {
System.out.println("Impossible");
}
}
//交换次数
private static int cnt = 0;
private static boolean haveMiddle = false;
/**
* @param arr 数组
* @param i 0
* @param i1 最后索引
* @param oe true为偶数 false 为基数
* 1. 先判断奇偶,奇数有中间字母,偶数没有。
* 2. odd-even 奇偶
* @return false不是回文
*/
private static boolean palindrome(char[] arr, int a, int b) {
if (b <= a)
return true;
for (int i = b; i > a; i--) {
//从右往左遍历,如果有一样的则调换,如果没有则判断是否可能为中间字母。
if (arr[a] == arr[i]) {
exchange(arr, i, b);
cnt += exchangeTimes(i, b);
return palindrome(arr, a + 1, b - 1);
}
}
// 遍历了一遍,没有找到一样的
if (!haveMiddle) {
haveMiddle = true;
cnt += exchangeTimes(a, arr.length / 2);
return palindrome(arr, a + 1, b);
}
return false;
}
private static int exchangeTimes(int a, int b) {
return b - a;
}
//一个字符顺序交换
private static void exchange(char[] arr, int a, int b) {
char temp = arr[a];
for (int i = a; i < b; i++) {
arr[i] = arr[i + 1];
}
arr[b] = temp;
}
}