交換的定義是:交換兩個相鄰的字符
例如mamad
第一次交換 ad : mamda
第二次交換 md : madma
第三次交換 ma : madam (迴文!完美!)
第二行是一個字符串,長度爲N.只包含小寫字母
否則輸出Impossible
mamad
3
貪心算法
思路:
先判斷出現字母的個數爲奇數的數量_count,若_count>1,就是impossible;如果_count爲零,就是所有的都能配對成功,左邊開始固定一個字母,就從右邊對稱位置開始往左邊搜,第一個遇到一樣的字母的就向右移到對應的位置。一直如此重複就解出來了;
單是_count=1時,尋找時會遇到找不到的情況,應爲這個字母就是放在最中間,這個時候就要從右邊開始固定,開始從左邊開始位置向右邊找,這樣的話中間的那一個最後自己就到最中間去了;
接下來設定一種理想情況,就是不會被破壞的情況,就是最後迴文中靠近兩邊的字母一定是更早到達對應的位置,因爲如果是中間的元素更早到達平衡位置,你再調外側的元素內側一定會被打亂,所以假設一種理想情況,即不會被打亂的情況,那麼假設此時移動的次數爲理想距離;如果移動配對兩側的元素,他就是理想距離,但是配對兩側的元素的時候由於移動會使一些字母偏離理想距離,又會使一些字母更靠近理想距離,爲什麼呢,應爲這樣的操作會使字母往中間靠攏,有元素大於理想距離,就一定有元素小於理想距離,所以移動的總次數一定不會超過理想距離,所以這樣的策略一定是對的。
/**
*
*/
package 基礎練習;
import java.awt.Checkbox;
import java.util.Scanner;
/**
* @author Administrator 問題描述
* 迴文串,是一種特殊的字符串,它從左往右讀和從右往左讀是一樣的。小龍龍認爲迴文串纔是完美的。現在給你一個串,它不一定是迴文的,
* 請你計算最少的交換次數使得該串變成一個完美的迴文串。 交換的定義是:交換兩個相鄰的字符 例如mamad 第一次交換 ad : mamda
* 第二次交換 md : madma 第三次交換 ma : madam (迴文!完美!) 輸入格式
* 第一行是一個整數N,表示接下來的字符串的長度(N <= 8000) 第二行是一個字符串,長度爲N.只包含小寫字母 輸出格式
* 如果可能,輸出最少的交換次數。 否則輸出Impossible 樣例輸入 5 mamad 樣例輸出 3
*/
public class 完美的代價 {
/**
* @param args
*/
private static int change = 0; // 改變的次數
private static int old = 0; // 記錄出現奇數次字符
private static char charold = 0;// 記錄奇數字符
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
int N = Integer.parseInt(sc.nextLine());
String s = sc.nextLine();
char str[] = s.toCharArray();
Boolean flag = check(str); // 是否可以組成迴文
if (!flag) {
System.out.println("Impossible");
} else {
for (int i = 0; i < N / 2; i++) {
if (str[i] != charold) {// 從右開始找對稱
int j = 0;
for (j = N - 1 - i; j > i; j--) {
if (str[i] == str[j])// 找到
break;
}
change += N - 1 - i - j; // 移動次數
for (int j2 = j; j2 < N - 1; j2++) {
str[j2] = str[j2 + 1];
}
str[N - 1 - i] = str[i];// 對稱點
}
// 從左邊開始
else {
int j = 0;
for (j = i; j < N - 1 - i; j++) {
if (str[j] == str[N - 1 - i])
break;// 找到
}
change += j - i;// 移動次數
for (int j2 = j; j2 < i; j2--) {
str[j2] = str[j2 - 1];
}
str[i] = str[N - 1 - i]; // 對稱點
}
}
System.out.println(change);
}
}
private static boolean check(char[] str) {
int arr[] = new int[26];
for (int i = 0; i < str.length; i++) {
arr[str[i] - 'a']++;
}
for (int i = 0; i < 26; i++) {
if (arr[i] % 2 == 1) {
old++;
charold = (char) (i + 'a');
}
}
if (old > 1)
return false;
return true;
}
}
提交到藍橋杯系統只得了60分。 有四個沒有ac不知道什麼原因。還在研究中。。。。