1.暴力枚举(--其实我还不会写,有待改进的地方是先把枚举学懂是学习算法的第一步…)O(n^3)通不过测试--
要改进的地方:
1.要有函数式的思维(把过程拆分为多个函数)
2.提前写好算法步骤再逐步优化
3.要有从1个数据到多个数据分类讨论的思想(画思维导图)
4.刚开始学不要贪图时间复杂度大小,能写出来再优化
5.把大困难分解成为多个小困难
代码思路:
1.字符串长度为1时直接返回
2.枚举全部情况的字符组合顺序(先去思考怎么把元素全部列举出来)
3.需要的步骤包括 列举每个值的函数和判断单个字符是回文数的函数
4.枚举字符串的套路可以记下来,因为是固定的,由于subString的特点(第二个值是去闭区间的),所以循环的j变量要<=s.length();
5.如果当前最大回文数的长度大于之前遍历的长度,则更新长度
6.判断是否是回文数的函数就是一一在中间对称对比字符串,前面的从0开始,后面的从length-i-1开始,i的条件是;length/2.在中间结束循环
7. 6的判断为什么不考虑回文数的奇数偶性呢? 因为length/2刚刚好处理了对称问题…
---- 如 abc length/2=1 中心在b刚刚好不用对比, abba 中心在length/2=2中心在b
----当i加到2的时候刚刚好,落在index=2的b,
----s.charAt(2)!=s.charAt(2) b=b所以不用处理了
//暴力解法
class Solution {
public static void main(String[] args) {
Solution solution = new Solution();
String abc = solution.longestPalindrome("aacabdkacaa");
System.out.println(abc);
}
public String longestPalindrome(String s) {
//长度为1的字符串的单独考虑
if(s.length()==1) return s;
int maxlength=0;
String ans="";
for(int i=0;i<s.length()-1;i++){
//注意j<=s.length(),因为substring(i,j) 截取的字符串区间是前闭后开的,即[i,j)
for(int j=i+1;j<=s.length();j++){
String temp=s.substring(i,j);
if(isPalindrome(temp)&&temp.length()>maxlength){
ans=temp;
maxlength=ans.length();
}
}
}
return ans;
}
//判断是否是回文串的函数
public boolean isPalindrome(String s){
int length=s.length();
for(int i=0;i<length/2;i++){
if(s.charAt(i)!=s.charAt(length-i-1)){
return false;
}
}
return true;
}
}
2.中心扩散法(大佬的方法)
个人总结:
0.中心扩散法是指从中心一个特定的值,扩散到他两边的值
1.中间的值对比两边的值,设了三个变量 left(左边的下标) right(右边的下标) len(找到的长度)
2.中间的值对比两边的值, 左边找到了 就 left–.右边找到了就right++
3.如果都没有找到,那么直接对比 ,left-1和right+1的值 如果相等就len+2 ,否则 介绍寻找
–
实践调试代码后的总结
1.为什么叫中心扩散法,就是以for循环的i下标为中心!!! 然后i的下标的值对比两边的值
2.如果相等向外面扩散,最后一步是如果扩散后的值相等则长度+2.继续扩散
3.注意len都会清零,还是会重复对比中心继续扩散,直到i到length
4.但是注意边界条件, 也是套路 0 和length是常见的边界条件,left>=0和right<=length也是常见的套路
思路
代码:
public class test02 {
public static void main(String[] args) {
test02 test02 = new test02();
String res = test02.longestPalindrome1("aabb");
System.out.println(res);
}
public String longestPalindrome1(String s) {
//判空,??为什么是长度为1的时候不直接返回??
if (s == null || s.length() == 0) {
return "";
}
//得到字符串长度
int strLen = s.length();
//左边字符的下标
int left = 0;
//右边边字符的下标
int right = 0;
//???长度为什么为1??? 答: 因为必须肯定要最少一个数进行对比
int len = 1;
//最大子串的开始下标
int maxStart = 0;
//最大的长度
int maxLen = 0;
for (int i = 0; i < strLen; i++) {
left = i - 1;
right = i + 1;
while (left >= 0 && s.charAt(left) == s.charAt(i)) {
len++;
left--;
}
while (right < strLen && s.charAt(right) == s.charAt(i)) {
len++;
right++;
}
while (left >= 0 && right < strLen && s.charAt(right) == s.charAt(left)) {
len = len + 2;
left--;
right++;
}
if (len > maxLen) {
maxLen = len;
maxStart = left;
}
//黑人问号??? 为什么len重置为1? 答:接下来的循环会继续寻找 其他子串
len = 1;
}
return s.substring(maxStart + 1, maxStart + maxLen + 1);
}
}