题目:给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。
示例1:
输入: "aacecaaa"
输出: "aaacecaaa"
示例2:
输入: "abcd"
输出: "dcbabcd"
算法思路:借鉴 每日一道算法面试题(5):leetcode5 最长回文子串 查找最长回文串的思路,先找到字符串中的最大回文串,在此基础上在最大回文串的左边或右边添加字符使之成为的回文串就是最短回文串。由于题目要求在字符串前面添加字符,即查找到的最大回文串中包含的左边字符串的字符数量要大于等于右边字符串的数量,否则就需要在右边补齐了,而且肯定要包括左边第一个字符,因为如果不包括第一个字符在补齐的时候应该在字符串右边相应位置补齐这个字符,所以最大回文串的中心点要在字符串的左边或中心位置而且要包含第一个字符,即只需要从左边遍历一半字符串的长度查找包含第一个字符的最长回文串。
算法代码:根据算法思路,写出的算法具体代码如下:
public String shortestPalindrome(String s) {
if (s == null || s.length() == 0) {
return "";
}
int len = s.length();
int maxLength = 0;
int maxStart = 0;
int maxEnd = 0;
for(int i = 0; i <= len / 2; i ++) {
int findLen1 = expandAroundCenter(s, i, i); // 考虑“aba”的情况
int findLen2 = expandAroundCenter(s, i, i + 1); // 考虑“cbbc”的情况
int findLen = Math.max(findLen1, findLen2);
int finStart = i - (findLen - 1) / 2;
if (findLen > maxLength && finStart == 0) {
maxLength = findLen;
maxStart = 0;
maxEnd = i + findLen / 2;
}
}
String needAdd;
if (maxStart == 0 && len > 1) {
needAdd = s.substring(maxEnd + 1);
} else if (len > 1){
needAdd = s.substring(1);
} else {
needAdd = null;
}
if (needAdd != null && needAdd.length() > 0) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = needAdd.length() - 1; i >= 0; i --) {
stringBuilder.append(needAdd.charAt(i));
}
stringBuilder.append(s);
return stringBuilder.toString();
}
return s;
}
// 中心扩展算法:返回最大的回文字符串长度
public int expandAroundCenter(String s, int left, int right) {
int len = s.length();
while (left >= 0 && right < len && s.charAt(left) == s.charAt(right)) {
left --;
right ++;
}
if (left < 0 || right >= len || s.charAt(left) != s.charAt(right)) {
left ++;
right --;
}
return right - left + 1;
}
如果你有疑问或更好的算法思路,欢迎留言交流!!!
如果感觉我的文章对您有所帮助,麻烦动动小手给个喜欢,谢谢!!!
网友评论