算法的重要性,我就很少說了吧,想去大廠,就必需要通過基礎知識和業務邏輯面試+算法面試。因此,爲了提升你們的算法能力,這個號後續天天帶你們作一道算法題,題目就從LeetCode上面選 !今天和你們聊的問題叫作 最短迴文串,咱們先來看題面:https://leetcode-cn.com/problems/shortest-palindrome/
You are given a string s. You can convert s to a palindrome by adding characters in front of it.面試
Return the shortest palindrome you can find by performing this transformation.算法
題意
給定一個字符串 s,你能夠經過在字符串前面添加字符將其轉換爲迴文串。找到並返回能夠用這種方式轉換的最短迴文串。
示例
示例 1:
輸入:s = "aacecaaa"
輸出:"aaacecaaa"
示例 2:
輸入:s = "abcd"
輸出:"dcbabcd"
提示:
0 <= s.length <= 5 * 104
s 僅由小寫英文字母組成
解題
思路一:暴力破解法
要找到知足題目要求的最短迴文串,本質是要找到最長的迴文子串,該子串的左端點與字符串s的左端點重合。時間複雜度是O(n ^ 2),其中n爲字符串s的長度。空間複雜度是O(n)。JAVA代碼:class Solution {
public String shortestPalindrome(String s) {
int index = -1;
for(int i = s.length() - 1; i >= 0; i--){
if(isPalindrome(s.substring(0, i + 1))){
index = i;
break;
}
}
String result = reverse(s.substring(index + 1));
return result + s;
}
private String reverse(String s){
StringBuilder stringBuilder = new StringBuilder(s);
return stringBuilder.reverse().toString();
}
private boolean isPalindrome(String s){
for(int i = 0; i < s.length() / 2; i++){
if(s.charAt(i) != s.charAt(s.length() - 1 - i)){
return false;
}
}
return true;
}
}思路二:遞歸解法左指針i初始化爲0,右指針j從n - 1遞減到0,其中n爲字符串s的長度,一旦趕上i指向的字符與j指向的字符相等時,令i指針加1。遞歸出口:若是i指針最後的值等於n,說明字符串s自己就是迴文串,直接返回s便可。遞歸過程:首先明確一點:咱們所要尋找的最長迴文子串,該子串的左端點與字符串s的左端點重合,必定在[0, i)範圍內。考慮兩種極端狀況,第一種狀況:字符串s自己就是迴文串,顯然知足條件。第二種狀況:在遍歷過程當中,不存在i指向的字符與j指向的字符相等的狀況,除了i和j相等時,這種狀況咱們獲得的i是1。顯然也知足條件。考慮通常性狀況:假設咱們所要尋找的最長迴文子串不在[0, i)範圍內,即存在迴文串其在[0, k)範圍內,其中k > i。那麼顯然,在咱們遍歷的過程當中,即便j在[k, n - 1]範圍時不存在i指向的字符與j指向的字符相等的狀況,最終i的值也會到達k,即i >= k,這顯然矛盾了,所以該結論成立。由上述結論,咱們得出:[i, n - 1]範圍內的子串必定不是咱們所要尋找的最長迴文子串的一部分。這樣,咱們就能夠遞歸地反轉[0, i)範圍內的子串來拼接出結果。時間複雜度是O(n ^ 2),其中n爲字符串s的長度。空間複雜度是O(n)。JAVA代碼:class Solution {
public String shortestPalindrome(String s) {
int i = 0;
for(int j = s.length() - 1; j >= 0; j--){
if(s.charAt(j) == s.charAt(i)){
i++;
}
}
if(i == s.length()){
return s;
}
return reverse(s.substring(i)) + shortestPalindrome(s.substring(0, i)) + s.substring(i);
}
private String reverse(String s){
StringBuilder stringBuilder = new StringBuilder(s);
return stringBuilder.reverse().toString();
}
}思路三:KMP算法將原字符串s和其逆序字符串用「#」拼接在一塊兒,利用KMP算法中next數組的求法求得拼接出的新字符串的最長相同先後綴,就是原字符串s中最長的迴文子串,該子串的左端點與字符串s的左端點重合。這個問題是一個動態規劃問題:求取字符串s中的最長相同先後綴(不能是其自己)狀態定義:f(x) -------- 字符串s中[0, x]範圍內的最長相同先後綴(不能是其自己)的長度狀態轉移:首先是初始化,f(0)顯然是0,由於[0, 0]範圍內的字符串長度爲1,其最長相同先後綴根本不存在。對於i在[1, n - 1](其中n爲字符串s的長度)範圍內的值:(1)令temp記錄f(x - 1)的值,若是temp大於0且s中temp位置的字符和第i個字符不相同,那麼咱們就須要重設temp的值爲f(temp - 1)。(2)若是s中第i個字符與第temp個字符相同,令temp自增1。(3)f(i) = temp。上述狀態轉移過程可能很難理解,以一個例子——「ABABCABAA」來講明,其子串以下:A -------------------------------------------------- 0AB ------------------------------------------------ 0ABA ---------------------------------------------- 1ABAB -------------------------------------------- 2ABABC ------------------------------------------ 0ABABCA ---------------------------------------- 1ABABCAB -------------------------------------- 2ABABCABA ------------------------------------ 3ABABCABAA ---------------------------------- 1對由ABAB求得ABABC這個過程進行分析:C和A不相等,所以結果不多是3,若是是ABABA,則結果是3。ABAB的結果是2,所以咱們知道AB和AB相同,可是第一個AB以後跟着的是A,依然和C不相同。咱們繼續看AB,AB的結果是0,所以咱們知道AB中A和B不相同,而C和A不相同,所以結果是0。對由ABABCABA求得ABABCABAA這個過程進行分析:A和B不相等,所以結果不多是4,若是是ABABCABAB,則結果是4。ABABCABA的結果是3,所以咱們知道ABA和ABA相同,可是第一個ABA以後跟着的是B,依然和A不相同。咱們繼續看ABA,ABA的結果是1,可是第一個A以後跟着的是B,依然和A不相同。咱們繼續看A,結果是0,結束while循環。這個A和A相同,所以其值加1變成1。時間複雜度和空間複雜度均是O(n),其中n爲字符串s的長度。JAVA代碼:class Solution {
public String shortestPalindrome(String s) {
String rev = reverse(s);
String temp = s + "#" + rev;
int[] next = getNext(temp);
return rev.substring(0, rev.length() - next[temp.length() - 1]) + s;
}
private String reverse(String s){
StringBuilder stringBuilder = new StringBuilder(s);
return stringBuilder.reverse().toString();
}
private int[] getNext(String s){
int[] result = new int[s.length()];
result[0] = 0;
for(int i = 1; i < result.length; i++){
int temp = result[i - 1];
while(temp > 0 && s.charAt(i) != s.charAt(temp)){
temp = result[temp - 1];
}
if(s.charAt(i) == s.charAt(temp)){
temp++;
}
result[i] = temp;
}
return result;
}
}好了,今天的文章就到這裏 。
![watermark,size_16,text_QDUxQ1RP5Y2a5a6i,color_FFFFFF,t_100,g_se,x_10,y_10,shadow_90,type_ZmFuZ3poZW5naGVpdGk=](http://static.javashuo.com/static/loading.gif)