题目描述

原题链接

给你一个字符串 s,找到 s 中最长的回文子串。

示例 1:

输入:s = “babad” 输出:”bab” 解释:”aba” 同样是符合题意的答案。

示例 2:

输入:s = “cbbd” 输出:”bb”

提示:

1 <= s.length <= 1000
s 仅由数字和英文字母组成

个人解法

JavaScript

  1. function fun(s) {
  2. let i = 0;
  3. let j = s.length - 1;
  4. while(i < j){
  5. if(s[i] === s[j]){
  6. i ++;
  7. j --;
  8. }
  9. else {
  10. return false;
  11. }
  12. }
  13. return true;
  14. }
  15. /**
  16. * @param {string} s
  17. * @return {string}
  18. */
  19. var longestPalindrome = function (s) {
  20. let str = '';
  21. let subStr = '';
  22. const length = s.length;
  23. if (length <= 0) {
  24. return "";
  25. }
  26. for (let i = 0; i < length; i++) {
  27. if (length - i < str.length) {
  28. break;
  29. }
  30. for (let j = i + 1; j <= length; j++) {
  31. if (j - i < str.length) {
  32. continue;
  33. }
  34. subStr = s.substring(i, j);
  35. if (fun(subStr)) {
  36. if (subStr.length > str.length) {
  37. str = subStr;
  38. }
  39. }
  40. }
  41. }
  42. return str;
  43. };

Java(暴力解法)

大致思路就是从字串长度最大(字符串原始长度)开始找,每次减1,找到的第一个回文子串便是我们要的答案。
值得注意的是,我们在进行回文数判断的时候,拿事先取出的数组进行判断(将字符串转化为一个char数组)

  1. class Solution {
  2. public String longestPalindrome(String s) {
  3. String longS = s.substring(0,1);
  4. char[] cs = s.toCharArray();
  5. int max = 1, j = 0,len=s.length();
  6. for(max=len;max>=1;max--){
  7. for(j=0;j<=len-max;j++){
  8. if (judge(cs,j, j + max-1)) {
  9. longS=s.substring(j, j + max);
  10. max=0;
  11. break;
  12. }
  13. }
  14. }
  15. return longS;
  16. }
  17. private boolean judge(char[] cs, int i, int j) {
  18. while (i < j) {
  19. if (cs[i] != cs[j]) {
  20. return false;
  21. }
  22. i++;
  23. j--;
  24. }
  25. return true;
  26. }
  27. }

更优解法

JavaScript

动态规划

  1. /**
  2. * @param {string} s
  3. * @return {string}
  4. */
  5. var longestPalindrome = function (s) {
  6. let str = '';
  7. const length = s.length;
  8. let arr = new Array(length);
  9. if (length <= 0) {
  10. return "";
  11. }
  12. if(length === 1){
  13. return s;
  14. }
  15. for (let i = 0; i < length; i++) {
  16. arr[i] = new Array(length);
  17. }
  18. for (let i = 0; i < length; i++) {
  19. for (let j = 0; j < length; j++) {
  20. if (i === j) {
  21. arr[i][j] = true;
  22. }
  23. arr[i][j] = null;
  24. }
  25. }
  26. for (let L = 1; L <= length; L++) {
  27. for (let i = 0; i < length; i++) {
  28. let j = L + i - 1;
  29. if (j >= length) {
  30. break;
  31. }
  32. if (s[i] !== s[j]) {
  33. arr[i][j] = false;
  34. } else {
  35. if (j - i < 3) {
  36. arr[i][j] = true;
  37. } else {
  38. arr[i][j] = arr[i + 1][j - 1];
  39. }
  40. }
  41. if (arr[i][j] && j - i + 1 > str.length) {
  42. str = s.substring(i, j + 1);
  43. }
  44. }
  45. }
  46. return str;
  47. };

中心扩散法

  1. /**
  2. * @param {string} s
  3. * @return {string}
  4. */
  5. function longestPalindrome(s) {
  6. let Resleft = 0;
  7. let Resright = 0;
  8. let maxLen = 0;
  9. let i = 0; //设i为中心的索引
  10. while (i < s.length) {
  11. let left = i - 1;
  12. while (left >= 0 && s[i] === s[left]) {
  13. left--;
  14. }
  15. let right = i + 1;
  16. while (right < s.length && s[i] === s[right]) {
  17. right++;
  18. }
  19. const end = right; //这里的right是右边第一个跟中心s[i]不相等的字符索引,保存下来,等会i直接跳到end处,可减少重复中心的计算
  20. while (left >= 0 && right < s.length && s[left] === s[right]) {
  21. left--;
  22. right++;
  23. }
  24. if (maxLen < right - left - 1) {
  25. maxLen = right - left - 1;
  26. Resleft = left + 1;
  27. Resright = right - 1;
  28. }
  29. i = end;
  30. }
  31. return s.substring(Resleft, Resright + 1);
  32. };

Java

动态规划

  1. public class Solution {
  2. public String longestPalindrome(String s) {
  3. int len = s.length();
  4. //当长度为1时,直接返回s
  5. if (len < 2) {
  6. return s;
  7. }
  8. int maxLen = 1;
  9. int begin = 0;
  10. // dp[i][j] 表示 s[i..j] 是否是回文串
  11. boolean[][] dp = new boolean[len][len];
  12. // 初始化:所有长度为 1 的子串都是回文串
  13. for (int i = 0; i < len; i++) {
  14. dp[i][i] = true;
  15. }
  16. //将字符串转化为字符数组,便于后面进行s字符串第i位和第j位的字符是否相等的判断
  17. char[] charArray = s.toCharArray();
  18. // 递推开始
  19. // 先枚举子串长度
  20. for (int L = 2; L <= len; L++) {
  21. // 枚举左边界,左边界的上限设置可以宽松一些
  22. for (int i = 0; i < len; i++) {
  23. // 由 L 和 i 可以确定右边界,即 j - i + 1 = L 得
  24. int j = L + i - 1;
  25. // 如果右边界越界,就可以退出当前循环
  26. if (j >= len) {
  27. break;
  28. }
  29. //charArray[i] != charArray[j]代表s[i...j]必定不是回文串
  30. if (charArray[i] != charArray[j]) {
  31. dp[i][j] = false;
  32. } else {
  33. //bb,aba 存在两种初始情况
  34. if (j - i < 3) {
  35. dp[i][j] = true;
  36. } else {
  37. //i位j位相等,s[i...j]是否为回文串取决于s[i+1...j-1]
  38. //a bcb a(是)a bcd a(不是)
  39. dp[i][j] = dp[i + 1][j - 1];
  40. }
  41. }
  42. // 只要 dp[i][L] == true 成立,就表示子串 s[i..L] 是回文,此时记录回文长度和起始位置
  43. if (dp[i][j] && j - i + 1 > maxLen) {
  44. maxLen = j - i + 1;
  45. begin = i;
  46. }
  47. }
  48. }
  49. return s.substring(begin, begin + maxLen);
  50. }
  51. }

中心扩散法

  1. class Solution {
  2. public String longestPalindrome(String s) {
  3. if (s == null || s.length() < 1) {
  4. return "";
  5. }
  6. int start = 0, end = 0;
  7. for (int i = 0; i < s.length(); i++) {
  8. //初始中心可能是a b a(b是中心)也可能是a bb a(bb是中心)
  9. int len1 = expandAroundCenter(s, i, i);
  10. int len2 = expandAroundCenter(s, i, i + 1);
  11. int len = Math.max(len1, len2);
  12. if (len > end - start) {
  13. start = i - (len - 1) / 2;
  14. end = i + len / 2;
  15. }
  16. }
  17. return s.substring(start, end + 1);
  18. }
  19. //从初始中心开始拓展,如果是回文数,每次继续判断边界两位置字符是否一样
  20. public int expandAroundCenter(String s, int left, int right) {
  21. while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
  22. --left;
  23. ++right;
  24. }
  25. return right - left - 1;
  26. }
  27. }