[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

516. Longest Palindromic Subsequence

647. Palindromic Substrings

LeetCode 题目总结

posted @ 2020-04-09 13:59  CNoodle  阅读(498)  评论(0编辑  收藏  举报