BASIC-19 / Tsinsen 1043 完美的代價(java)
問題描述
迴文串,是一種特殊的字串,它從左往右讀和從右往左讀是一樣的。小龍龍認為迴文串才是完美的。現在給你一個串,它不一定是迴文的,請你計算最少的交換次數使得該串變成一個完美的迴文串。
交換的定義是:交換兩個相鄰的字元
例如mamad
第一次交換 ad : mamda
第二次交換 md : madma
第三次交換 ma : madam (迴文!完美!)
交換的定義是:交換兩個相鄰的字元
例如mamad
第一次交換 ad : mamda
第二次交換 md : madma
第三次交換 ma : madam (迴文!完美!)
輸入格式
第一行是一個整數N,表示接下來的字串的長度(N <= 8000)
第二行是一個字串,長度為N.只包含小寫字母
第二行是一個字串,長度為N.只包含小寫字母
輸出格式
如果可能,輸出最少的交換次數。
否則輸出Impossible
否則輸出Impossible
樣例輸入
5
mamad
mamad
樣例輸出
3
題目分析:
求把一個字串變成迴文串的最小交換次數,有難度,需要仔細分析移動過程,分析出演算法。
演算法分析:
貪心演算法。為什麼會想到用貪心演算法呢,慢慢分析思路,如何交換才能得到迴文串並且要保證次數最少。如果先將兩端進行對稱,再從兩端不斷向中間推進,再推進的過程不再影響到兩端的字元,而是隻與當前的狀態有關,這樣每次都是區域性最優,屬於貪心演算法。必然也是次數最少的方法。
具體如何實現呢,我們從左向右地去遍歷陣列,然後再從右向左地查詢對稱的字元。
如果從兩端不斷向中間推進的過程裡,左右兩端的指標i,j重合了,說明這是單獨的字元,要進行計數,比如本題中d是單獨字元。這裡分析一下,如果總長為偶數,則必然是Impossible,很好理解,一個偶數串裡有一個單獨的字元,是不可能成為迴文串的。比較難理解的是總長為奇數的情況,如果出現了單獨字元,我們可以先跳過它,但是如果出現了第二個單獨字元,則Impossible了,奇數串裡存在兩個單獨字元,只交換相鄰字元,也不能夠得到迴文串了。分析得出了兩種Impossible的情況之後,我們考慮怎麼去處理剛剛跳過的單獨字元,其實也不用考慮,移動到最中心去就好了。
上面分析的是左右兩端的指標i,j重合的情況。如果兩端的指標i,j重合沒有重合,就很好辦了,說明找到了相同字元,比如本題第一位是m,就從右向左地查詢到了第一個m的位置。要做的就是把m移動到最後去。這樣我們就把左邊第一位和右第一位進行了對稱。然後把右端向中間推進一位。
下面迴圈整個過程就可以,比如把m移動好之後,就從右向左地繼續找和左邊第二位的a一樣的字元,如果找到了,就把它的位置換到倒數第二位,不斷對稱,也符合最初所說的貪心演算法,也就是無後效性和區域性最優的兩個特性。
演算法設計:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
char[] a = new char[n];
a = sc.next().toCharArray();
sc.close();
int j = n - 1;
int single = 0;
int sum = 0;
int k, i;
for (i = 0; i < j; i++) { //從左向右遍歷
k = j;
while (a[i] != a[k]) {
k--; //從右向左查詢
}
if (k == i) { //從兩端不斷向中間推進,左右兩端的指標i,j重合
single++; //單獨的字母
if (n % 2 == 0 || single > 1) {
//總長為偶數則Impossible
//總長為奇數,先跳過這個單獨字母,出現第二個單獨字母則Impossible
System.out.println("Impossible");
return;
} else {
sum += n / 2 - i; //單獨的字母移動到中心
}
} else { //從兩端不斷向中間推進,左右兩端的指標i,j未重合
for (int m = k; m < j; m++) { //交換到最後一個位置去
a[m] = a[m + 1];
}
sum += j - k;
j--; //右端向中間推進
}
}
System.out.println(sum);
}
}
相關文章
- BASIC-17 / Tsinsen 1041 矩陣乘法(java)矩陣Java
- PAT1043 輸出PATest(java實現)Java
- java----volatile, 用更低的代價替代同步Java
- 並行的代價並行
- 最小連通代價
- java_完數Java
- 陣列的最大代價陣列
- 現代 CSS 高階技巧,完美的波浪進度條效果!CSS
- 模型表示及代價函式模型函式
- DEVOPS也是要有代價的dev
- 蘋果iPhone歷代成本對比 初代價效比封神蘋果iPhone
- 執行計劃的代價估算
- 技術債務真正的代價
- 函式呼叫的代價與優化函式優化
- 沒學過C語言的代價C語言
- Java分代垃圾回收機制:年輕代/年老代/持久代(轉)Java
- Java培訓完能做什麼工作Java
- [譯] 程式設計師開會的代價程式設計師
- 往返讀取後臺資料的代價
- 低價區遊戲漲價出殺招 跨區代購要消失了?遊戲
- Java培訓完能不能就業?Java就業
- 讀完Java名著《Effective Java》: 我整理了這50條技巧Java
- Java有什麼優點?學完Java能找到工作嗎?Java
- 替換資料庫的代價與真假國產資料庫
- 11.2.0.2.0 bug? 簡單查詢代價異常
- Java能夠成為完美的技術平臺嗎?(轉)Java
- Java工程師學習指南(完結篇)Java工程師
- Java工程師學習指南 完結篇Java工程師
- Web服務效能測試:Node完勝JavaWebJava
- Java能做什麼?學完Java可以從事什麼工作呢?Java
- 成為真正的變革型CIO,代價幾何?
- 【dp】51nod 1270 陣列的最大代價陣列
- 技術債務:究竟讓你付出了多大代價?
- Java培訓完可以應用在什麼領域Java
- 學完Java後,你可以從事哪些崗位?Java
- Java怎麼樣?學完後前途怎麼樣?Java
- Java永久代去哪兒了Java
- ICA Client Error 1043: Invalid Parameter with a Towitoko CHIPDRIVE SIM Card ReaderclientError