题目
思路
- 暴力法
- 找到每个相同字符的下标i,j,然后再比较i,j区间的字符串是否为回文字符串,是则记录此时最大的长度的回文字符串
- 中心扩散方法
- 以每个下标开始扩散,判断其左右两边最大长度能够满足回文,并记录此时的长度
代码
1.暴力超时 public String longestPalindrome(String s) { int len = s.length(); if (len <= 1) return s; String res = ""; for (int i = 0; i < len; i++) { for (int j = i + 1; j < len; j++) { if (s.charAt(i) == s.charAt(j)) { int m = i, n = j; while (m < n && s.charAt(m) == s.charAt(n)) { m++; n--; } String str = s.substring(i, j + 1); res = m >= n && str.length() > res.length() ? str : res; } } } return res.length() < 1 ? String.valueOf(s.charAt(0)) : res; } //2. 中心扩散方法 public String longestPalindrome(String s) { if (s == null) 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 end - start == 0 ? s.substring(0, 1) : s.substring(start, end + 1); } public int expandAroundCenter(String s, int left, int right) { while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) { left--; right++; } return right - left - 1; } //1.暴力递归 public String longestPalindrome(String s) { int start = 0, end = 0; for (int i = 0; i < s.length(); i++) { int len1 = recur(s, i, i + 1) + 2; int len2 = recur(s, i, i) + 1; int len = Math.max(len1, len2); if (len > end - start) { //偶数会多一位 start = i - (len - 1) / 2; end = i + len / 2 ; } } return end - start == 0 ? s.substring(0, 1) : s.substring(start, end + 1); } public int recur(String s, int i, int j) { if (i < 0 || j >= s.length()) return -2; if (s.charAt(i) == s.charAt(j)) return recur(s, i - 1, j + 1) + 2; return -2; } //2. 动态规划 public String longestPalindrome(String s) { //dp[i][j]表示字符串下标i到j之间是否为回文 int len = s.length(), start = 0, end = 0; boolean[][] dp = new boolean[len][len]; for (int i = 0; i < len; i++) { dp[i][i] = true; } for (int j = 1; j < len; j++) { for (int i = 0; i < j; i++) { if (s.charAt(i) != s.charAt(j)) { dp[i][j] = false; } else { if (j - i < 3) { dp[i][j] = true; } else { dp[i][j] = dp[i + 1][j - 1]; } if (dp[i][j] && j - i > end - start) { start = i; end = j; } } } } return end - start == 0 ? s.substring(0, 1) : s.substring(start, end + 1); }
最长回文子串