[LeetCode][5]Longest Palindromic Substring解析 -Java实现

Q:

Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.

A;

以下解法和代码没有借阅以往任何资料,如果有更好的解法请在评论区留言

这道题的大致意思是找出一个字符串中最长的回文子串,给的字符串最大长1000,只有一个最长子串。

我拿到这道题的时候感觉跟之前一道题很像啊-我自己写的LeetCode3,一个是求最长不重复串一个是求最长回文串。上次的时间复杂度是O(n)。我在想是不是可以用二分法(也就是分治思想)变成O(logn)呢,不然这题做着是不是没啥意思了。

首先我们肯定最后要把这个字符串分割成最小子串(长度为1)返回他自己,然后父方法再查找自己,这样就没意思了,因为子串和父串的最长重复子串之间没有必然联系,最后还是要遍历一下父串的,这样算法最后复杂度还是O(nlogn),在评论里求O(logn)解法。我这里换一种思路去解O(n)解法了。

首先,回文的性质如下:

1、回文正读和倒读都是一样的字符串

2、回文串中心对称

所以第一步可能我们需要先获取所有回文串然后找大小,如何确定一个字符串是回文串呢?

关于中心对称,但是我们如何快捷的找出这个中心对称的字符串就是个难点。

我们考虑一下人是怎么识别回文串的。

1、读取字符,在脑海中形成一种数据结构存储我们读取到的字符

2、对比都读到的字符是不是和上一个或者上上个字符一致,如果一致继续对比,直到不一致得出这是一个回文串。

如果这种想法我们转换成程序:

首先需要一个for来循环字符串这样就是O(n)

其次需要另一个隐藏起来的循环来对比相似的字符串,这个复杂度怎么算。。。好尴尬。

每一步只计算关于第一次发现重复位置的对称位置是否一致的话这样复杂度就成功到O(n)了。

来,让我们写个代码看看(代码比较复杂因为写了一个类进去)

public class LongestPalindromicSubstring {
	public static void main(String[] args){
		char[] m = "aaaaaa".toCharArray();
		System.out.println(method(m));
	}

	private static char[] method(char[] m) {
		// TODO Auto-generated method stub
		Palindromic maxP = new Palindromic();
		maxP.thisLength =0;
		maxP.thisFlag =0d;
		ArrayList<Palindromic> pList = new ArrayList<Palindromic>();
		for(int i =1;i<m.length;i++){
			if(i>=2){
				if(m[i]==m[i-1]){//与相邻的相等
					Palindromic p = new Palindromic();
					p.thisFlag  = ((double)i+(double)i-1.0d)/2.0d;
					p.thisLength =1;
					pList.add(p);
				}
				if(m[i]==m[i-2]){//隔一个与上一个相等
					Palindromic p = new Palindromic();
					p.thisFlag  = i-1.0d;
					p.thisLength =1;
					pList.add(p);
				}
				for(Palindromic p : pList){
					if(!p.isEnd){
						int symmetry =((int)p.thisFlag*2)-i;
						if(m[i]==m[symmetry]){
							p.thisLength++;
							if(symmetry==0){
								p.isEnd = true;
							}
						}else{
							p.isEnd = true;
						}
					}
				}

			}else{
				if(m[i]==m[i-1]){//与相邻的相等
					if(i==1){
						Palindromic p = new Palindromic();
						p.thisFlag  = ((double)i+(double)i-1.0d)/2.0d;
						p.thisLength = 1;
						p.isEnd = true;
						pList.add(p);
					}else{

						Palindromic p = new Palindromic();
						p.thisFlag  = ((double)i+(double)i-1.0d)/2.0d;
						p.thisLength = 1;
						pList.add(p);
					}

				}if(i==2&&m[i]==m[i-2]){//隔一个与上一个相等
					System.out.println("ok");
					Palindromic p = new Palindromic();
					p.thisFlag  = i-1.0d;
					p.thisLength = 1;
					pList.add(p);
				}
			}
		}
		for(Palindromic p: pList){
			int length;
			if(p.thisFlag/1.0d==0){
				length = p.thisLength*2-1;
			}else{
				length = p.thisLength*2;
			}
			int maxlength;
			if(maxP.thisFlag/1.0d==0){
				maxlength = maxP.thisLength*2-1;
			}else{
				maxlength = maxP.thisLength*2;
			}
			if(length>maxlength){
				maxP = p;
			}
		}
		if(maxP.thisFlag/1.0d==0){
			System.out.println(maxP);
			return Arrays.copyOfRange(m, (int)maxP.thisFlag-maxP.thisLength-1, (int)maxP.thisFlag+maxP.thisLength);
		}else{
			System.out.println(maxP);
			int flag = (int) Math.ceil(maxP.thisFlag);
			return Arrays.copyOfRange(m,flag-maxP.thisLength , flag+maxP.thisLength);
		}
		
	}
	static class Palindromic{
		public double thisFlag = 0;
		public int thisLength = 0;
		public boolean isEnd = false;
		@Override
		public String toString() {
			// TODO Auto-generated method stub
			return "falg:"+thisFlag+"....."+"thisLength:"+thisLength;
		}
	}

虽然代码量大,但是时间复杂度还可以,虽然没有预期的O(n)虽然有两层for嵌套,但是仔细算起来应该是趋近于O(n)这一种我也不会计算,因为第二个for循环变量太多了。。。。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值