题目

image.png

思路

  • 暴力法
    • 找到每个相同字符的下标i,j,然后再比较i,j区间的字符串是否为回文字符串,是则记录此时最大的长度的回文字符串
  • 中心扩散方法
    • 以每个下标开始扩散,判断其左右两边最大长度能够满足回文,并记录此时的长度

代码

  1. 1.暴力超时
  2. public String longestPalindrome(String s) {
  3. int len = s.length();
  4. if (len <= 1) return s;
  5. String res = "";
  6. for (int i = 0; i < len; i++) {
  7. for (int j = i + 1; j < len; j++) {
  8. if (s.charAt(i) == s.charAt(j)) {
  9. int m = i, n = j;
  10. while (m < n && s.charAt(m) == s.charAt(n)) {
  11. m++;
  12. n--;
  13. }
  14. String str = s.substring(i, j + 1);
  15. res = m >= n && str.length() > res.length() ? str : res;
  16. }
  17. }
  18. }
  19. return res.length() < 1 ? String.valueOf(s.charAt(0)) : res;
  20. }
  21. //2. 中心扩散方法
  22. public String longestPalindrome(String s) {
  23. if (s == null) return "";
  24. int start = 0, end = 0;
  25. for (int i = 0; i < s.length(); i++) {
  26. //奇数对称
  27. int len1 = expandAroundCenter(s, i, i);
  28. //偶数对称
  29. int len2 = expandAroundCenter(s, i, i + 1);
  30. int len = Math.max(len1, len2);
  31. if (len > end - start) {
  32. //偶数会多一位
  33. start = i - (len - 1) / 2;
  34. end = i + len / 2 ;
  35. }
  36. }
  37. return end - start == 0 ? s.substring(0, 1) : s.substring(start, end + 1);
  38. }
  39. public int expandAroundCenter(String s, int left, int right) {
  40. while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
  41. left--;
  42. right++;
  43. }
  44. return right - left - 1;
  45. }
  46. //1.暴力递归
  47. public String longestPalindrome(String s) {
  48. int start = 0, end = 0;
  49. for (int i = 0; i < s.length(); i++) {
  50. int len1 = recur(s, i, i + 1) + 2;
  51. int len2 = recur(s, i, i) + 1;
  52. int len = Math.max(len1, len2);
  53. if (len > end - start) {
  54. //偶数会多一位
  55. start = i - (len - 1) / 2;
  56. end = i + len / 2 ;
  57. }
  58. }
  59. return end - start == 0 ? s.substring(0, 1) : s.substring(start, end + 1);
  60. }
  61. public int recur(String s, int i, int j) {
  62. if (i < 0 || j >= s.length()) return -2;
  63. if (s.charAt(i) == s.charAt(j))
  64. return recur(s, i - 1, j + 1) + 2;
  65. return -2;
  66. }
  67. //2. 动态规划
  68. public String longestPalindrome(String s) {
  69. //dp[i][j]表示字符串下标i到j之间是否为回文
  70. int len = s.length(), start = 0, end = 0;
  71. boolean[][] dp = new boolean[len][len];
  72. for (int i = 0; i < len; i++) {
  73. dp[i][i] = true;
  74. }
  75. for (int j = 1; j < len; j++) {
  76. for (int i = 0; i < j; i++) {
  77. if (s.charAt(i) != s.charAt(j)) {
  78. dp[i][j] = false;
  79. } else {
  80. if (j - i < 3) {
  81. dp[i][j] = true;
  82. } else {
  83. dp[i][j] = dp[i + 1][j - 1];
  84. }
  85. if (dp[i][j] && j - i > end - start) {
  86. start = i;
  87. end = j;
  88. }
  89. }
  90. }
  91. }
  92. return end - start == 0 ? s.substring(0, 1) : s.substring(start, end + 1);
  93. }

最长回文子串