摘要:這種解法中,外層循環遍歷的是子字符串的中心點,內層循環則是從中心擴散,一旦不是回文就不再計算其他以此為中心的較大的字符串。
Longest Palindromic Substring
Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.暴力法 Brute Force 復雜度
時間 O(n^3) 空間 O(1)
思路暴力法就是窮舉所有子字符串的可能,然后依次按位判斷其是否是回文,并更新結果。雖然其時間復雜度很高,但它對空間的要求很低。
代碼public class Solution { public String longestPalindrome(String s) { int maxLength = 0; int maxStart = 0; int len = s.length(); //i是字符串長度 for(int i = 0; i < len; i++){ //j是字符串起始位置 for(int j = 0; j < len - i; j++){ //挨個判斷是否回文 if(isPalindrome(s,i,j) && (i+1)>maxLength){ maxLength = i + 1; maxStart = j; } } } return s.substring(maxStart,maxStart + maxLength); } private isPalindrome(String s, int i, int j){ int left = j; int right = j + i; while(left動態規劃 Dynamic Programming 復雜度 時間 O(n^2) 空間 O(n^2)
思路根據回文的特性,一個大回文按比例縮小后的字符串也必定是回文,比如ABCCBA,那BCCB肯定也是回文。所以我們可以根據動態規劃的兩個特點:第一大問題拆解為小問題,第二重復利用之前的計算結果,來解答這道題。那如何劃分小問題呢,我們可以先把所有長度最短為1的子字符串計算出來,根據起始位置從左向右,這些必定是回文。然后計算所有長度為2的子字符串,再根據起始位置從左向右。到長度為3的時候,我們就可以利用上次的計算結果:如果中心對稱的短字符串不是回文,那長字符串也不是,如果短字符串是回文,那就要看長字符串兩頭是否一樣。這樣,一直到長度最大的子字符串,我們就把整個字符串集窮舉完了,但是由于使用動態規劃,使計算時間從O(N^3)減少到O(n^2)。
注意外循環的變量控制的實際上不是字符串長度,而是字符串首到尾的增量
二維數組的第一維是指子字符串起始位置,第二維是指終止位置,所存數據表示是否回文
代碼public class Solution { public String longestPalindrome(String s) { int maxLength = 0; int maxStart = 0; int len = s.length(); boolean[][] dp = new boolean[len][len]; //i是字符串長度 for(int i = 0; i < len; i++){ //j是字符串起始位置 for(int j = 0; j < len - i; j++){ if(i==0||i==1){ //如果字符串長度為0,必定為回文 dp[j][j+i] = true; } else if(s.charAt(j+i)==s.charAt(j)){ //如果左右兩端相等,那只要中心對稱子字符串是回文就是回文 dp[j][j+i] = dp[j+1][j+i-1]; } else { //否則不是回文 dp[j][j+i] = false; } if(dp[j][j+i] && i > maxLength){ maxLength = i + 1; maxStart = j; } } } return s.substring(maxStart,maxStart + maxLength); } }中心擴散法 Spread From Center 復雜度時間 O(n^2) 空間 O(1)
思路動態規劃雖然優化了時間,但也浪費了空間。實際上我們并不需要一直存儲所有子字符串的回文情況,我們需要知道的只是中心對稱的較小一層是否是回文。所以如果我們從小到大連續以某點為個中心的所有子字符串進行計算,就能省略這個空間。 這種解法中,外層循環遍歷的是子字符串的中心點,內層循環則是從中心擴散,一旦不是回文就不再計算其他以此為中心的較大的字符串。由于中心對稱有兩種情況,一是奇數個字母以某個字母對稱,而是偶數個字母以兩個字母中間為對稱,所以我們要分別計算這兩種對稱情況。
代碼public class Solution { String longest = ""; public String longestPalindrome(String s) { for(int i = 0; i < s.length(); i++){ //計算奇數子字符串 helper(s, i, 0); //計算偶數子字符串 helper(s, i, 1); } return longest; } private void helper(String s, int idx, int offset){ int left = idx; int right = idx + offset; while(left>=0 && rightlongest.length()){ longest = currLongest; } } } 2018/2
class Solution: def longestPalindrome(self, s): """ :type s: str :rtype: str """ maxStr = "" for index in range(0, len(s)): sub1 = self.spreadFromCenter(s, index, 0) sub2 = self.spreadFromCenter(s, index, 1) if len(sub1) > len(maxStr): maxStr = sub1 if len(sub2) > len(maxStr): maxStr = sub2 return maxStr def spreadFromCenter(self, string, centerIndex, offset): leftIndex = centerIndex rightIndex = centerIndex + offset length = len(string) while leftIndex >= 0 and rightIndex < length and string[leftIndex] == string[rightIndex]: leftIndex = leftIndex - 1 rightIndex = rightIndex + 1 leftIndex = leftIndex + 1 substring = string[leftIndex:rightIndex] return substring馬拉車算法 Manacher Algorithm 復雜度時間 O(n) 空間 O(n)
關于時間復雜度的證明:http://www.zhihu.com/question...
思路Manacher算法是非常經典的計算連續下標回文的算法。它利用了回文的對稱性,更具體的來說,是回文內回文的對稱性,來解決這個問題。
代碼
參見:http://www.felix021.com/blog/...public class Solution { public String longestPalindrome(String s) { if(s.length()<=1){ return s; } // 預處理字符串,避免奇偶問題 String str = preProcess(s); // idx是當前能夠向右延伸的最遠的回文串中心點,隨著迭代而更新 // max是當前最長回文串在總字符串中所能延伸到的最右端的位置 // maxIdx是當前已知的最長回文串中心點 // maxSpan是當前已知的最長回文串向左或向右能延伸的長度 int idx = 0, max = 0; int maxIdx = 0; int maxSpan = 0; int[] p = new int[str.length()]; for(int curr = 1; curr < str.length(); curr++){ // 找出當前下標相對于idx的對稱點 int symmetryOfCurr = 2 * idx - curr; // 如果當前已知延伸的最右端大于當前下標,我們可以用對稱點的P值,否則記為1等待檢查 p[curr] = max > curr? Math.min(p[symmetryOfCurr], max - curr):1; // 檢查并更新當前下標為中心的回文串最遠延伸的長度 while((curr+p[curr])后續 Follow Upmax){ max = p[curr] + curr; idx = curr; } // 檢查并更新當前已知的最長回文串信息 if(p[curr]>maxSpan){ maxSpan = p[curr]; maxIdx = curr; } } //去除占位符 return s.substring((maxIdx-maxSpan)/2,(maxSpan+maxIdx)/2-1); } private String preProcess(String s){ // 如ABC,變為$#A#B#C# StringBuilder sb = new StringBuilder(); sb.append("$"); for(int i = 0; i < s.length(); i++){ sb.append("#"); sb.append(s.charAt(i)); } sb.append("#"); return sb.toString(); } } Q:如果只能在頭或尾刪,問最少刪多少字符能使得該字符串變為回文?
A:就是找到最長回文串,然后把長度減一下就行了。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/64389.html
摘要:難度題目是說給出一個字符串求出這個字符串的最長回文的子串回文是指前后完全對稱的字符串像是之類的都算是回文奇數字母的回文和偶數字母的回文中心是不一樣的奇數字母比如的中心在中間字母上偶數字母比如的回文在中間兩字母的中心上由此可見回文中心點實際上 Given a string s, find the longest palindromic substring in s. You may as...
摘要:一題目最長回文子串給定一個字符串,找到中最長的回文子串。你可以假設的最大長度為。示例輸入輸出注意也是一個有效答案。 一、題目 最長回文子串: 給定一個字符串 s,找到 s 中最長的回文子串。你可以假設 s 的最大長度為 1000。 示例 1: 輸入: babad輸出: bab注意: aba 也是一個有效答案。 示例 2: 輸入: cbbd輸出: bb 二、我的答案 思路 1.排...
摘要:題目即求最長回文子序列原題鏈接此篇博客僅為學習記錄我的解法及代碼暴力解決,用及進行兩層遍歷循環中套一層循環,用遍歷,求最長回文序列字符串,同時用變量記錄最長子序列這種寫法很暴力,效率很低,一層循環,一層循環,回文序列對比一層,時間復雜度為辣 題目: Given a string s, find the longest palindromic substring in s. You ma...
摘要:題目解析題目是要找出最長的回文字符串,拿到題目的第一反應是遍歷子串,然后一直替換最長的子字符串即可了。但是這種解法遇到極端輸入狀況就會超時,指定的最長長度為,遍歷子串需要兩次循環,判斷回文需要一次循環,所以總的效率為,那么極端狀況會超時。 題目 Given a string s, find the longest palindromic substring in s. You may ...
摘要:回文的意思就是反轉字符串后和原字符串相等。因為這種想法沒次都是兩邊同時擴展。所以要分目標字符串長度為奇數目標字符串為偶數兩種情況。 題目詳情 Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.題目的意思是輸入...
閱讀 2245·2021-11-24 11:15
閱讀 3093·2021-11-24 10:46
閱讀 1390·2021-11-24 09:39
閱讀 3930·2021-08-18 10:21
閱讀 1484·2019-08-30 15:53
閱讀 1400·2019-08-30 11:19
閱讀 3332·2019-08-29 18:42
閱讀 2329·2019-08-29 16:58