演算法實戰(五)最長回文子串

2022-02-05 07:23:02 字數 2942 閱讀 8597

今天開始第五題,求最長回文子串。不知不覺已經堅持到第五天了,往往在這個時候最容易大易,所以我們不能鬆懈,堅持就能走向成功。

題目:給定乙個字串 s,找到 s 中最長的回文子串。你可以假設 s 的最大長度為 1000。

示例1:輸入: "babad"

輸出: "bab"

注意: "aba" 也是乙個有效答案。

首先我們要明白什麼是回文字串,回文是乙個正讀和反讀都相同的字串,例如,「aba」 是回文,而「abc」 不是。

1)暴力破解法:首先看到這道題目,我最開始的思路就是用暴力破解法,首先拿到字串的所有字串,然後判斷字串是不是回文,最終找出最長的回文字串。但是拿到所有的子串所需要的時間複雜度是o(n^2),而判斷乙個字串是不是回文字串所需要的時間複雜度是o(n),所以暴力法的時間複雜度是o(n^3),不用想都知道leetcode上面肯定通過不了,於是我做了一些修改,去除了大部分不需要的判斷。話不多說,**如下: 

1

class

solution 7//

定義開始指標,用來指向回文的開始位置

8int begin = 0;9//

定義結束指標,用來指向回文的開始位置

10int end = 0;

11//

外層迴圈,遍歷每乙個字元

12for(int i = 0; i < s.length(); i++)

22//

判斷頭到index之間是不是回文的,如果是回文,計算差值是否大於全域性變數頭尾位置的差值

23if(checkstr(s, i, index) && index - i > end -begin)

29//

如果本次頭與index直接的距離已經小於全域性頭尾距離了,沒必要往下找了,直接跳出

30if (index - i < end -begin)

33//

更新j的值,繼續找j之前對應的字元位置

34 j = index - 1;35}

36}37return s.substring(begin, end + 1);38}

3940

//判斷乙個字串在【i,j】上是不是回文的

41public

boolean checkstr(string s, int i, int

j)46 i++;

47 j--;48}

49return

true;50

}51 }

2)上面那種方法可以通過測試,但是耗費的時間還是太長了。官方的解法應該是要使用動態規劃,但是本人是乙個演算法渣渣,還不會這種演算法,容我先去學習一天,明天補上,謝謝大家

動態規劃的學習篇章已經補上了:如果大家和我一樣對dp不是很熟係的可以先學習一下,接下來我們就按照這篇文章中的解題步驟來進行解題。解乙個dp的題,我認為首先是要定義好乙個狀態,然後再根據狀態來驗證是否滿足最優子結構和子問題重疊的性質,都滿足後進而推出狀態轉移方程。

1.狀態:f(i,j):表示以第i個字元開頭,以第j個字元結尾的字元的回文長度,如果是回文字元,則就是i到j之間的長度,如果不是回文字串則是0.

2.定性:最優子結構:我們知道了f(i,j)的長度,如果不為0的話,我們就可以推出f(i+1,j-1)的長度,能夠通過子問題的解得到原問題的解,滿足最優子結構。

重疊子問題:我們計算f(2,6)的時候,需要用到f(3,5)的解,計算f(3,5)的時候,需要使用到f(4,4)的解,如果不將f(3,5)的解儲存下來,f(4,4)會被重複計算,滿足重疊子問題。(重疊子問題不是dp解法的必要條件,但是有了重疊子問題這個性質,我們使用dp解這個題才有了優勢)

3.狀態轉移方程:狀態轉移方程的情況比較多,從這兩種不同的情況來看

1)當第i個字元和第j個字元相同時, f(i,j)=  1 (j - i = 0時,乙個字串就是長度為1的回文字串)  

2 (j - i = 1 ,兩個相鄰並且相同的字串就是長度為2的回文字串)

f(i+1, j - 1)+ 2 ,(當j - i > 1 並且f(i+1, j - 1)不為0時)

0 (j - i 》1 並且f(i+1, j - 1)為0時,子串的都不是回文字串,該字串也不是回文字串)

2)當第i個字元和第j個字元不相同時,f(i,j) = 0;

4.輔助空間,使用乙個二維陣列來儲存解

**如下:

1

class

solution 7//

用來儲存最大回文字串的開頭位置和結尾位置

8int begin = 0;

9int end = 0;

10//

二位陣列儲存解

11int arr = new

int[s.length()][s.length()];

12for (int j = 0; j < s.length(); j++)else

if (j - i == 1)else

22 }else

25//

將每一次的結果與begin和end的差值進行比較,如果大於,則進行替換,這樣計算完成後,儲存的就是最大值了

26if (arr[i][j] > end - begin + 1)30}

31}32return s.substring(begin, end + 1);33}

34 }

在我們分析完狀態轉移方程後,編寫**就是一件比較簡單的事了,在我個人看來,比較難理解的地方是兩次for迴圈本身的條件,為什麼內層迴圈是到i 《= j 的判斷條件,這個又要和我們的狀態扯上關係。狀態f(i,j)是要求字串以i開頭以j結尾時回文字串的長度,而我們在計算它的值時,需要用到 i 到 j 中間的子串的解,所以我們要先計算出這些解,才能將j往後移動。(ps:我不知道這樣解釋能不能看明白,要是還不明白的小夥伴可以在紙上畫一畫,就很清晰了)。這就是今天這個題的解法,大家有什麼不明白的,或者有其他的高見,歡迎一起**交流,謝謝!

最長回文子串 LeetCode 五 最長回文子串

題目 最長回文子串 給定乙個字串s,找到s中最長的回文子串。你可以假設s的最大長度為 1000。題目解析 回文?當回文串長度為奇數時,比如 北京計程車租出京北 當回文串長度為偶數的時候,比如 1221 以上兩種情況有乙個共同的特點就是有乙個中心,那在 中如何表示中心呢?class solution ...

演算法 最長回文子串

題目描述 對於乙個字串,請設計乙個高效演算法,計算其中最長回文子串的長度。給定字串a以及它的長度n,請返回最長回文子串的長度。例如 輸入 abc1234321ab 12 返回值 7 最長回文子串 public static intgetlongestpalindrome string a,int n...

最長回文串 演算法 4 求解最長回文子串

問題描述 給定乙個字串 s,找到 s 中最長的回文子串。你可以假設 s 的最大長度為 1000。注釋 回文通俗的說就是正著念和反著念都一樣,如 上海自來水來自海上。示例 1 輸入 dabccbac 輸出 abccba 示例 2 輸入 cbbd 輸出 bb 解題思路 此處撰寫解題思路 遍歷每乙個索引,...