题目 给你一个字符串 s,找到 s 中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
示例 1:
1 2 3 输入:s = "babad" 输出:"bab" 解释:"aba" 同样是符合题意的答案。
示例 2:
提示:
1 <= s.length <= 1000
s 仅由数字和英文字母组成
我的解答 思路,两次循环直接遍历所有可能性。O(n^2) 的时间复杂度。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class Solution { public String longestPalindrome (String s) { if (s.length() == 1 ){ return s; } int n = s.length(); String result = "" ; for (int i = 0 ; i < n; i++){ for (int j= i+1 ; j<=n ; j++){ int length = result.length(); if (length >= j-i){ continue ; } String sub = s.substring(i,j); if (isPalindrome(sub) ){ result = sub; } } } return result; } private boolean isPalindrome (String s) { int length = s.length(); int mid = length/2 ; for (int i = 0 ;i< mid; i++){ if (s.charAt(i) != s.charAt(length-i-1 )){ return false ; } } return true ; } }
官方参考 第二种解答方法,中心扩散法。 因为所有的相同字符串都算是回文 ,只要找到两边第一个与中心不相等的位置,相互判断是否相等来判断是否是回文。 遍历每一个元素,以其为中心向两边扩散判断是否回文即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 class Solution { public String longestPalindrome (String s) { if (s == null || s.length() == 0 ) { return "" ; } if ( s.length() == 1 ) { return s; } int strLen = s.length(); int left = 0 ; int right = 0 ; int len = 1 ; int maxStart = 0 ; int maxLen = 0 ; for (int i = 1 ; i < strLen; i++) { left = i - 1 ; right = i + 1 ; while (left >= 0 && s.charAt(left) == s.charAt(i)) { len++; left--; } while (right < strLen && s.charAt(right) == s.charAt(i)) { len++; right++; } while (left >= 0 && right < strLen && s.charAt(right) == s.charAt(left)) { len = len + 2 ; left--; right++; } if (len > maxLen) { maxLen = len; maxStart = left; } len = 1 ; } return s.substring(maxStart + 1 , maxStart + maxLen + 1 ); } }
但是以上的解法都有很多重复的计算,解决方法是使用动态规划,记录做过的重复计算。
对于一个子串而言,如果它是回文串,并且长度大于2,那么将它首尾的两个字母去除之后,它仍然是个回文串。
动态规划主要是找到初始状态和状态转移方程。初始状态 i=j ,此时dp[i][j]=true , 状态转移方程dp[i][j]=true 并且(i-1)和(j+1)两个位置为相同的字符,此时 dp[i-1][j+1]=true。
注意填充顺序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 public class Solution { public String longestPalindrome (String s) { int len = s.length(); if (len < 2 ) { return s; } int maxLen = 1 ; int begin = 0 ; boolean [][] dp = new boolean [len][len]; for (int i = 0 ; i < len; i++) { dp[i][i] = true ; } char [] charArray = s.toCharArray(); for (int L = 2 ; L <= len; L++) { for (int i = 0 ; i < len; i++) { int j = L + i - 1 ; if (j >= len) { break ; } if (charArray[i] != charArray[j]) { dp[i][j] = false ; } else { if (j - i < 3 ) { dp[i][j] = true ; } else { dp[i][j] = dp[i + 1 ][j - 1 ]; } } if (dp[i][j] && j - i + 1 > maxLen) { maxLen = j - i + 1 ; begin = i; } } } return s.substring(begin, begin + maxLen); } }
官方讲解https://leetcode.cn/problems/longest-palindromic-substring/solution/zui-chang-hui-wen-zi-chuan-by-leetcode-solution/
链接:https://leetcode.cn/problems/longest-palindromic-substring