[LeetCode] 5. 最长回文子串
好难呜呜呜呜
方法一:动态规划
class Solution { public String longestPalindrome(String s) { if(s.equals("")) return ""; String origin=s; String reverse=new StringBuffer(s).reverse().toString(); int length=s.length(); int[][] arr=new int[length][length]; int maxLen=0; int maxEnd=0; for(int i=0;i<length;i++){ for(int j=0;j<length;j++){ if(origin.charAt(i)==reverse.charAt(j)){ if(i==0||j==0){ arr[i][j]=1; }else{ arr[i][j]=arr[i - 1][j - 1] + 1; } } /**********修改的地方*******************/ if(arr[i][j]>maxLen){ int beforeRev=length-j-1; if (beforeRev + arr[i][j] - 1 == i) { //判断下标是否对应 maxLen = arr[i][j]; maxEnd = i; } } } } //return s.substring(maxEnd - maxLen + 1, maxEnd + 1); return s.substring(maxEnd-maxLen+1,maxEnd+1); } }
方法二:相比于方法一 对arr数组进行了优化,把二维降为一维
class Solution { public String longestPalindrome(String s) { if(s.equals("")) return ""; String origin=s; String reverse=new StringBuffer(s).reverse().toString(); int length=s.length(); int[]arr=new int[length]; int maxLen=0; int maxEnd=0; for(int i=0;i<length;i++){ for(int j=length-1;j>=0;j--){ if(origin.charAt(i)==reverse.charAt(j)){ if(i==0||j==0){ arr[j]=1; }else{ arr[j]=arr[j - 1] + 1; } }else{ arr[j]=0; } if(arr[j]>maxLen){ int beforeRev=length-j-1; if (beforeRev + arr[j] - 1 == i) { //判断下标是否对应 maxLen = arr[j]; maxEnd = i; } } } } return s.substring(maxEnd-maxLen+1,maxEnd+1); } }
没有什么实质性的提高哈。
liweiwei1419 给出的动态规划的答案
public class Solution { public String longestPalindrome(String s) { int len = s.length(); if (len < 2) { return s; } boolean[][] dp = new boolean[len][len]; for (int i = 0; i < len; i++) { Arrays.fill(dp[i], false); } // 初始化 for (int i = 0; i < len; i++) { dp[i][i] = true; } char[] charArray = s.toCharArray(); int maxLen = 1; int start = 0; for (int j = 1; j < len; j++) { for (int i = 0; i < j; i++) { dp[i][j] = charArray[i] == charArray[j] && (j - i < 3 || dp[i + 1][j - 1]); // 只要 dp[i][j] == true 成立,就表示子串 s[i, j] 是回文,此时记录回文长度和起始位置 if (dp[i][j]) { int curLen = j - i + 1; if (curLen > maxLen) { maxLen = curLen; start = i; } } } } return s.substring(start, start + maxLen); } }
方法三:中心扩散
public class Solution { public String longestPalindrome(String s) { int len = s.length(); if (len < 2) { return s; } int maxLen = 1; String res = s.substring(0, 1); // 中心位置枚举到 len - 2 即可 for (int i = 0; i < len - 1; i++) { String oddStr = centerSpread(s, i, i); String evenStr = centerSpread(s, i, i + 1); String maxLenStr = oddStr.length() > evenStr.length() ? oddStr : evenStr; if (maxLenStr.length() > maxLen) { maxLen = maxLenStr.length(); res = maxLenStr; } } return res; } private String centerSpread(String s, int left, int right) { // left = right 的时候,此时回文中心是一个字符,回文串的长度是奇数 // right = left + 1 的时候,此时回文中心是一个空隙,回文串的长度是偶数 int len = s.length(); int i = left; int j = right; while (i >= 0 && j < len) { if (s.charAt(i) == s.charAt(j)) { i--; j++; } else { break; } } // 这里要小心,跳出 while 循环时,恰好满足 s.charAt(i) != s.charAt(j),因此不能取 i,不能取 j return s.substring(i + 1, j); } }