leetcode——5.Longest Palindromic Substring(java)

5 篇文章 0 订阅
5 篇文章 0 订阅

题目:找到最大的回文子串

首先,回文串就是左右对称的字符串。要解这道题首先应该知道如何判断一个字符串是否是回文串。

我的思想很简单,就是定义两个指针i,j,初始指向字符串头和尾,依次向里收缩。长度为奇数的字符串最后两个指针相遇,即i=j。长度为偶数的字符串最后相邻,即j=i+1。直到最后,若i和j满足上面的这个条件,则说明该字符串是回文串。然后再通过遍历,找到最长的回文子串。这个算法的复杂度应该是O(n^2) 。  

我想上面这种算法应该是最容易想到的一种算法。但是要注意一下,在获得一个回文子串时,保存当前的长度,下次遍历的时候窗口最小设为这个长度,这样可以稍微减少一点运算时间。比如:在第一提交代码时我没有考虑这个问题,leetcode会报Time Limit Exceeded ,输入字符串为1000个d,这个字符串如果没有考虑窗口大小的话就会从第一位d开始,一直遍历到最后一位,然后确定这整个字符串是一个回文串,但是还会从第二位d开始继续遍历,但其实后面的子串长度肯定不会超过第一次的长度。所以后面的操作是没有意义的。

class Solution {
   public boolean isPalindrome(String s){
		boolean isOrNot = true;
		int size = s.length();
		int i=0,j = size-1;
		while(j>=i){
			char c1 = s.charAt(i);
			char c2 = s.charAt(j);
			if(c1 == c2){
				i++;
				j--;
			}else{
				isOrNot = false;
				break;
			}
		}
		return isOrNot;
	}
	
	public String longestPalindrome(String s) {
        if(s.length()==0){
			return s;
		}
		int location = 0;
		int size = 1; //最大窗口值
		int i = 0;  //左侧指针
		int j = 1;  //右侧指针
		while(i<s.length()-1&&j<s.length()){
			String substring = s.substring(i, j+1);
			if(isPalindrome(substring)){
				if(size < j-i+1){
					size = j-i+1;
					location = i;
				}
			}
			j++;
			if(j==s.length()) {
				i++;
				j = i+size;
			}
		}
		String ans = s.substring(location,size+location);
		return ans;
	}
}

考虑优化算法,用动态规划可以减少运行时间。

下面考虑动态规划算法。

判断一个字符串是否是回文串,只要首字符和尾字符相等,然后中间剩下的部分也是回文串,那么整个字符串就是回文串,如果首字符和尾字符不相等,那么一定不是回文串。考虑边界,若只有一个字符,则肯定是,若相邻,首字符尾字符相等也肯定是回文串,当字符串长度大于2时,若首尾相同,判断中间部分是否是回文串即可。

这样我们需要定义一个标志数组,存储从当前是否时回文串。label[i][j] 表示从i到j位的子串是否是回文串。

看下面这个例子 :输入串为“babad"

标志数组为(将其初始化全为0,只更新i<=j的部分)下表行代表i,列代表j值

 i,j01234
010000
101000
210100
311010
400001

当更新标志数组时,同时判断子串长度,如果是回文串,就判断是否应该更新最大子串长度和此时的i值。算法结束后,可以由子串长度和子串开始位置得到该最长子串。

class Solution {
   public String longestPalindrome(String s){
		int size = s.length();
		int [][]label = new int[size][size]; //标志数组
		int maxLength = 0; //存储最长子串的长度
		int location = 0;  //存储最长子串的起始位置
		int i = size-1 , j = size-1;  //初始时 i,j都为最后一位下标
		while(i>=0){
			j = i;
			while(j<size){
				char c1 = s.charAt(i);
				char c2 = s.charAt(j);
				if(c1==c2){
					if(j-i<2){
						label[i][j] = 1;
					}else{
						label[i][j] = label[i+1][j-1];
					}
				}else{
					label[i][j] = 0;
				}
				if(label[i][j]==1&&maxLength<j-i+1){
					maxLength = j-i+1;
					location = i;
				}
				j++;
			}
			i--;
		}
		String ans = s.substring(location,maxLength+location);
		return ans;
	}
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值