这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战
1.leetcode最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
示例 3:
输入:s = "a"
输出:"a"
方法1
暴力循环判断,双重循环获取每一个字符字串,判断每个字串是否回文串,判断记录下最长的回文串的位置,最后切割返回。
class Solution {
public String longestPalindrome(String s) {
int len = s.length();
// 空串和一个字符的直接返回本身
if (len < 2) {
return s;
}
// 拆成数组 用数组下标来访问字符比较
char[] chars = s.toCharArray();
// 记录最长回文串的长度
int maxLen = 1;
// 记录最长回文串开始位置
int p = 0;
// 循环遍历判断每个子字符串
for (int i = 0; i < len - 1; i++) {
for (int j = i + 1; j < len; j++) {
// 如果当前字符串是回文串且长度大于记录的回文串长度
if (j - i + 1 > maxLen && hui(chars, i, j)) {
maxLen = j - i + 1;
p = i;
}
}
}
// 返回最长的回文串
return s.substring(p, maxLen + p);
}
/**
* 判断是否回文数
*
* @param chars 字符串
* @param i 开始位置
* @param j 结束位置
* @return
*/
private boolean hui(char[] chars, int i, int j) {
while (i < j) {
// 循环判断字符串两边元素,如果不等就不是回文串
if (chars[i++] != chars[j--]) {
return false;
}
}
return true;
}
}
方法2
还有一种方法,以一个字符串为坐标,向左右两边遍历,比较左右两个字符是否相等,直到遇到不相等的,那么在这之前的字符串就是回文串,但是需要考虑,起点的问题,比如aba,abba这种,有可能是以一个字符开始向两边查找,也有可能是以两个字符开始,所以都需要判断。以当前遍历的字符或者当前字符和下个字符开始,往左右两边扩散查找,找到一个回文串,判断之前的是否比记录的大,是则需要更新记录下目前最大的回文串的下标,直到查找完成,最后根据下标substring返回目标字符串。
public String longestPalindrome(String s) {
// 记录最长的回文串 是长度的一半
int maxLen = 0;
int tempLen = 0;
// 记录回文串的开始结束位置->[left,right)
int left = 0;
int right = 0;
for (int i = 0; i < s.length(); i++) {
// 长度比当前记录的大,就更新一下
tempLen = huiWen(s, i, i);
if (tempLen > maxLen) {
maxLen = tempLen;
left = i - (tempLen / 2);
right = i + (tempLen / 2) + 1;
}
// 长度比当前记录的大,就更新一下
tempLen = huiWen(s, i, i + 1);
if (tempLen > maxLen) {
maxLen = tempLen;
left = i - ((tempLen / 2) - 1);
right = i + (tempLen / 2) + 1;
}
}
return s.substring(left, right);
}
/**
* 返回回文串的半长,然后根据这个算出坐标。
* @param s
* @param i
* @param j
* @return
*/
public int huiWen(String s, int i, int j) {
while (i >= 0 && j < s.length()) {
if (s.charAt(i) != s.charAt(j)) {
break;
}
i--;
j++;
}
return j - (i + 1);
}