回文字符串—回文子串—中心扩散法
leetcode地址:5. 最長(zhǎng)回文子串
解答參考:動(dòng)態(tài)規(guī)劃、中心擴(kuò)散、Manacher 算法
問(wèn)題描述:
給你一個(gè)字符串?s,找到?s?中最長(zhǎng)的回文子串。比如給定字符串s = "babad" ,找出最長(zhǎng)的回文子串為"bab"
算法思路:
本題可以采用暴力破解法、中心擴(kuò)散法、Manacher算法3種方法,本篇文章講解暴力破解法。
暴力法采用雙指針兩邊夾,驗(yàn)證是否是回文子串。除了枚舉字符串的左右邊界以外,比較容易想到的是枚舉可能出現(xiàn)的回文子串的“中心位置”,從“中心位置”嘗試盡可能擴(kuò)散出去,得到一個(gè)回文串。因此中心擴(kuò)散法的思路是:遍歷每一個(gè)索引,以這個(gè)索引為中心,利用“回文串”中心對(duì)稱的特點(diǎn),往兩邊擴(kuò)散,看最多能擴(kuò)散多遠(yuǎn)。枚舉“中心位置”時(shí)間復(fù)雜度為 O(N),從“中心位置”擴(kuò)散得到“回文子串”的時(shí)間復(fù)雜度為 O(N),因此時(shí)間復(fù)雜度可以降到 O(N^2)。在這里要注意一個(gè)細(xì)節(jié):回文串在長(zhǎng)度為奇數(shù)和偶數(shù)的時(shí)候,“回文中心”的形式是不一樣的。
- 奇數(shù)回文串的“中心”是一個(gè)具體的字符,例如:回文串 "aba" 的中心是字符 "b";
- 偶數(shù)回文串的“中心”是位于中間的兩個(gè)字符的“空隙”,例如:回文串串 "abba" 的中心是兩個(gè) "b" 中間的那個(gè)“空隙”。
我們看一下一個(gè)字符串可能的回文子串的中心在哪里?我們可以設(shè)計(jì)一個(gè)方法,兼容以上兩種情況:
- 如果傳入重合的索引編碼,進(jìn)行中心擴(kuò)散,此時(shí)得到的回文子串的長(zhǎng)度是奇數(shù);
- 如果傳入相鄰的索引編碼,進(jìn)行中心擴(kuò)散,此時(shí)得到的回文子串的長(zhǎng)度是偶數(shù)。
具體編碼細(xì)節(jié)在以下的代碼的注釋中體現(xiàn)。
public class Solution {public String longestPalindrome(String s) {int len = s.length();if (len < 2) {return s;}int maxLen = 1;String res = s.substring(0, 1);// 中心位置枚舉到 len - 2 即可for (int i = 0; i < len - 1; i++) {String oddStr = centerSpread(s, i, i);String evenStr = centerSpread(s, i, i + 1);String maxLenStr = oddStr.length() > evenStr.length() ? oddStr : evenStr;if (maxLenStr.length() > maxLen) {maxLen = maxLenStr.length();res = maxLenStr;}}return res;}private String centerSpread(String s, int left, int right) {// left = right 的時(shí)候,此時(shí)回文中心是一個(gè)字符,回文串的長(zhǎng)度是奇數(shù)// right = left + 1 的時(shí)候,此時(shí)回文中心是一個(gè)空隙,回文串的長(zhǎng)度是偶數(shù)int len = s.length();int i = left;int j = right;while (i >= 0 && j < len) {if (s.charAt(i) == s.charAt(j)) {i--;j++;} else {break;}}// 這里要小心,跳出 while 循環(huán)時(shí),恰好滿足 s.charAt(i) != s.charAt(j),因此不能取 i,不能取 jreturn s.substring(i + 1, j);} }總結(jié)
以上是生活随笔為你收集整理的回文字符串—回文子串—中心扩散法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 回文字符串—回文子串—暴力破解法
- 下一篇: 回文字符串—回文子串—Manacher算