一.前言
今天开始第五题,求最长回文子串。不知不觉已经坚持到第五天了,往往在这个时候最容易大易,所以我们不能松懈,坚持就能走向成功。
二.题目
题目:给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例1:输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
三.解题思路
首先我们要明白什么是回文字符串,回文是一个正读和反读都相同的字符串,例如,“aba” 是回文,而“abc” 不是。
1)暴力破解法:首先看到这道题目,我最开始的思路就是用暴力破解法,首先拿到字符串的所有字串,然后判断字串是不是回文,最终找出最长的回文字串。但是拿到所有的子串所需要的时间复杂度是O(n^2),而判断一个字符串是不是回文字符串所需要的时间复杂度是O(n),所以暴力法的时间复杂度是O(n^3),不用想都知道leetCode上面肯定通过不了,于是我做了一些修改,去除了大部分不需要的判断。话不多说,代码如下:
1 class Solution { 2 public String longestPalindrome(String s) { 3 //如果为空,直接返回 4 if (s == null || s.length() == 0){ 5 return s; 6 } 7 //定义开始指针,用来指向回文的开始位置 8 int begin = 0; 9 //定义结束指针,用来指向回文的开始位置 10 int end = 0; 11 //外层循环,遍历每一个字符 12 for(int i = 0; i < s.length(); i++){ 13 Character ch = s.charAt(i); 14 //内层循环,寻找回文 15 for(int j = s.length() - 1; j >= 0; ){ 16 //从字符串的末尾开始寻找与头字符匹配的字符串 17 int index = s.lastIndexOf(ch, j); 18 //如果没有,则这个字符串不可能是回文的,直接返回 19 if(index == -1){ 20 break; 21 } 22 //判断头到index之间是不是回文的,如果是回文,计算差值是否大于全局变量头尾位置的差值 23 if(checkStr(s, i, index) && index - i > end - begin){ 24 //大于则直接更新,并跳出本次循环 25 begin = i; 26 end = index; 27 break; 28 } 29 //如果本次头与index直接的距离已经小于全局头尾距离了,没必要往下找了,直接跳出 30 if (index - i < end - begin){ 31 break; 32 } 33 //更新j的值,继续找j之前对应的字符位置 34 j = index - 1; 35 } 36 } 37 return s.substring(begin, end + 1); 38 } 39 40 //判断一个字符串在【i,j】上是不是回文的 41 public boolean checkStr(String s, int i, int j){ 42 while(i <= j){ 43 if(s.charAt(i) != s.charAt(j)){ 44 return false; 45 } 46 i++; 47 j--; 48 } 49 return true; 50 } 51 }
2)上面那种方法可以通过测试,但是耗费的时间还是太长了。官方的解法应该是要使用动态规划,但是本人是一个算法渣渣,还不会这种算法,容我先去学习一天,明天补上,谢谢大家