leetcode-5-最长回文子串*马拉车
方法一:动态规划 O(n2) O(n2)
class Solution: def longestPalindrome(self, s: str) -> str: size = len(s) if size <= 1: return s # 二维 dp 问题 # 状态:dp[l,r]: s[l:r] 包括 l,r ,表示的字符串是不是回文串 # 设置为 None 是为了方便调试,看清楚代码执行流程 dp = [[False for _ in range(size)] for _ in range(size)] longest_l = 1 res = s[0] # 因为只有 1 个字符的情况在最开始做了判断 # 左边界一定要比右边界小,因此右边界从 1 开始 for r in range(1, size): for l in range(r): # 状态转移方程:如果头尾字符相等并且中间也是回文 # 在头尾字符相等的前提下,如果收缩以后不构成区间(最多只有 1 个元素),直接返回 True 即可 # 否则要继续看收缩以后的区间的回文性 # 重点理解 or 的短路性质在这里的作用 if s[l] == s[r] and (r - l <= 2 or dp[l + 1][r - 1]): dp[l][r] = True cur_len = r - l + 1 if cur_len > longest_l: longest_l = cur_len res = s[l:r + 1] # 调试语句 # for item in dp: # print(item) # print('---') return res
java:
class Solution { public String longestPalindrome(String s) { if (s == null || s.length() < 2) { return s; } int strLen = s.length(); int maxStart = 0; //最长回文串的起点 int maxEnd = 0; //最长回文串的终点 int maxLen = 1; //最长回文串的长度 boolean[][] dp = new boolean[strLen][strLen]; for (int r = 1; r < strLen; r++) { for (int l = 0; l < r; l++) { if (s.charAt(l) == s.charAt(r) && (r - l <= 2 || dp[l + 1][r - 1])) { dp[l][r] = true; if (r - l + 1 > maxLen) { maxLen = r - l + 1; maxStart = l; maxEnd = r; } } } } return s.substring(maxStart, maxEnd + 1); } }
方法二:中心扩展法 O(n^2)
class Solution: def longestPalindrome(self, s): size = len(s) if size == 0: return '' # 至少是 1 longest_palindrome = 1 longest_palindrome_str = s[0] for i in range(size): palindrome_odd, odd_len = self.__center_spread(s, size, i, i) palindrome_even, even_len = self.__center_spread(s, size, i, i + 1) # 当前找到的最长回文子串 cur_max_sub = palindrome_odd if odd_len >= even_len else palindrome_even if len(cur_max_sub) > longest_palindrome: longest_palindrome = len(cur_max_sub) longest_palindrome_str = cur_max_sub return longest_palindrome_str def __center_spread(self, s, size, left, right): """ left = right 的时候,此时回文中心是一条线,回文串的长度是奇数 right = left + 1 的时候,此时回文中心是任意一个字符,回文串的长度是偶数 """ l = left r = right while l >= 0 and r < size and s[l] == s[r]: l -= 1 r += 1 return s[l + 1:r], r - l - 1
java:
class Solution { public String longestPalindrome(String s) { if (s == null || s.length() < 1) return ""; int start = 0,end = 0; for (int i = 0; i < s.length(); i++){ int len1 = expandAroundCenter(s,i,i); int len2 = expandAroundCenter(s,i,i + 1); int len = Math.max(len1,len2); if (len > end - start){ start = i - (len - 1) / 2; end = i + len / 2; } } return s.substring(start,end + 1); } private int expandAroundCenter(String s,int left,int right){ int L = left, R = right; while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)){ L--; R++; } return R - L -1; } }