[LeetCode] 5. Longest Palindromic Substring
Given a string s
, return the longest palindromic substring in s
.
Example 1:
Input: s = "babad" Output: "bab" Explanation: "aba" is also a valid answer.
Example 2:
Input: s = "cbbd" Output: "bb"
Constraints:
1 <= s.length <= 1000
s
consist of only digits and English letters.
最长的回文子串。
题意是给一个字符串,请输出其中最长的回文子串。
这个题有两种做法,一个是中心扩散法,一个是DP。无论是DP还是中心扩散法,都需要注意两种不同的case,一种是aba,回文中间只有一个字母;另一种是abba,回文中间是两个字母的。
首先是中心扩散法。思路是把每一个字母或者每一对字母都当做回文的中心,然后试着向外扩增。注意12行(JS)取substring的范围,为什么是left + 1是因为第8行while循环最后一次是true的时候,多执行了一次left--和right++,所以在退出while循环的时候left和right的位置都比回文的部分往外扩增了一步。但由于substring的右边界是开区间所以right部分不需要 + 1。
时间O(n^2)
空间O(1)
JavaScript实现
1 /** 2 * @param {string} s 3 * @return {string} 4 */ 5 var longestPalindrome = function (s) { 6 let res = ''; 7 var checkPalindrome = function (s, left, right) { 8 while (left >= 0 && right < s.length && s[left] === s[right]) { 9 left--; 10 right++; 11 } 12 let cur = s.substring(left + 1, right); 13 if (cur.length > res.length) { 14 res = cur; 15 } 16 } 17 18 if (s === null || s.length === 0) return ''; 19 for (let i = 0; i < s.length; i++) { 20 checkPalindrome(s, i, i); 21 checkPalindrome(s, i, i + 1); 22 } 23 return res; 24 };
Java实现
1 class Solution { 2 String res = ""; 3 4 public String longestPalindrome(String s) { 5 // 注意数据范围,这里不需要判断字符串为空的corner case了 6 for (int i = 0; i < s.length(); i++) { 7 helper(s, i, i); 8 helper(s, i, i + 1); 9 } 10 return res; 11 } 12 13 private void helper(String s, int left, int right) { 14 while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) { 15 left--; 16 right++; 17 } 18 String cur = s.substring(left + 1, right); 19 if (cur.length() > res.length()) { 20 res = cur; 21 } 22 } 23 }
之后是DP的做法。既然是DP,就需要先得出小范围的解,然后再拓展到大范围的解。这里需要用到一个二维数组来记录DP的解。这里DP数组的定义是字符串[i, j]是否是回文。这是个闭区间。
JS代码12行判断dp[i][j]的时候,一定要先判断j - i是否小于等于2,因为是要保证j在i的右侧,或者起码i和j要在同一个位置上,否则之后的判断(dp[i + 1][j - 1])是没有意义的。有一种回文的情况是aba类型的,如果此时i和j都在b的位置上,那么判断dp[i + 1][j - 1]是没有意义的。
时间O(n^2)
空间O(n^2)
Java实现
1 class Solution { 2 public String longestPalindrome(String s) { 3 // corner case 4 if (s == null || s.length() == 0) { 5 return s; 6 } 7 8 // normal case 9 String res = ""; 10 boolean[][] dp = new boolean[s.length()][s.length()]; 11 int max = 0; 12 for (int j = 0; j < s.length(); j++) { 13 for (int i = j; i >= 0; i--) { 14 dp[i][j] = s.charAt(i) == s.charAt(j) && ((j - i <= 2) || dp[i + 1][j - 1]); 15 if (dp[i][j] && j - i + 1 > max) { 16 max = j - i + 1; 17 res = s.substring(i, j + 1); 18 } 19 } 20 } 21 return res; 22 } 23 }
JavaScript实现
1 /** 2 * @param {string} s 3 * @return {string} 4 */ 5 var longestPalindrome = function (s) { 6 const m = s.length; 7 const dp = [...new Array(m)].map(() => new Array(m).fill(false)); 8 let max = 0; 9 let res = ''; 10 for (let j = 0; j < m; j++) { 11 for (let i = 0; i <= j; i++) { 12 dp[i][j] = s[i] === s[j] && ((j - i <= 2) || dp[i + 1][j - 1]); 13 if (dp[i][j]) { 14 if (j - i + 1 > max) { 15 max = j - i + 1; 16 res = s.substring(i, j + 1); 17 } 18 } 19 } 20 } 21 return res; 22 };
相关题目
5. Longest Palindromic Substring