完美的代價,完美代價
問題描述
迴文串,是一種特殊的字串,它從左往右讀和從右往左讀是一樣的。小龍龍認為迴文串才是完美的。現在給你一個串,它不一定是迴文的,請你計算最少的交換次數使得該串變成一個完美的迴文串。
交換的定義是:交換兩個相鄰的字元
例如mamad
第一次交換 ad : mamda
第二次交換 md : madma
第三次交換 ma : madam (迴文!完美!)
輸入格式
第一行是一個整數N,表示接下來的字串的長度(N <= 8000)
第二行是一個字串,長度為N.只包含小寫字母
輸出格式
如果可能,輸出最少的交換次數。
否則輸出Impossible
範例輸入
5
mamad
範例輸出
3
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class Main {
public static void main(String[] args) throws Exception {
int n, i;
//檔案流輸出 Scanner sc = new Scanner(new File("test.in"));
while (sc.hasNext())
{
n = Integer.parseInt(sc.nextLine());
// 用數組arr[]保留輸入的數,
String str = sc.nextLine();
char arr[] = str.toCharArray();
// 用ch來保留出現的出現一次的不同的字母
char ch = '0';
// 用ch1來記錄出現不同字母的次數
int ch1 = 0;
// 用count[]數組來記錄每個字母出現的次數
int index;
int count[] = new int[26];
for (i = 0; i < arr.length; i++)
{
index = arr[i] - 'a';
count[index]++;
}
show(count, ch, ch1, arr, n);
}
}
private static void show(int[] count, char ch, int ch1, char arr[], int n)
{
// TODO Auto-generated method stub
// 開始計算出現不同字母出現一次的個數並把它記錄下來
for (int j = 0; j < count.length; j++)
{
if (count[j] % 2 != 0)
{ ch1++;
ch = (char) (j + 'a');
}
}
// 如果超過了兩個或著以上,那麼這樣肯定不能構成迴文數組
if (ch1 > 1)
{
System.out.println("Impossible");
}
// 只有一個不同字母的時候,進行冒泡法的尋找。調用find(),並返回結果;
else
{
int result = find(arr, ch, n);
System.out.println(result);
}
}
private static int find(char[] arr, char ch, int n)
{
// TODO Auto-generated method stub
// 尋找的思想是利用冒泡法的思維,同時從左右兩段開始掃描,找到相同的就break,記錄下來它的位置
// 確定迴圈的範圍
int i, count = 0, j, k;
for (i = 0; i < n / 2; i++)
{
// 從左邊向右邊掃描,第一個就是唯一不同的字母,遍曆比較
if (arr[i] == ch)
{
for (j = 0; j < n - 1 - i; j++)
{
// 構造迴文數,當第一個字母和最後一個相同(arr[n-i-1]是固定)並吧它的位置記錄下來為進行交換準備,沒遇到繼續,下一個掃描
if (arr[j] == arr[n - i - 1]) break;
}
count += j - i;
// 記錄下位置後,開始交換其他位置的數,從右邊開始往左掃描去,
// 假如dmmaa--->(找到了第三個位置的a和最後一個相同,所以a到d位置)dmmma---->ddmma結束,
for (k = j; k > i; k--)
{
arr[k] = arr[k - 1];
}
// 這裡就是構造迴文數,既是和最後一個字母相同的字母到第一個的位置,找到了,就進行下一個的掃描
arr[i] = arr[n - i - 1];
}
// 從右邊開始掃描,
else
{
for (j = n - 1 - i; j >= i; j--)
{
if (arr[j] == arr[i]) break;
}
count += n - 1 - i - j;
// 從右邊n-1-i開始,到j結束,所以從左開始往回掃描,從j開始掃描
for (k = j; k < n - 1 - i; k++)
{
arr[k] = arr[k + 1];
}
arr[n - i - 1] = arr[i];
}
}
return count;
}
}