【LeetCode 5】最长回文子串

思路1

失败思路

  希望通过双指针,O(n)的时间复杂度得到回文子串,但是仅仅能通过不到50%的测试样例。
写的还是挺简洁的,但是问题出现在"abdbab"时,无法给出最长回文子串"bab"。原因在于,两侧指针只有向中间靠拢的过程,而没有回退到原来位置的过程,指针在中间位置的"db"相遇。

public static String longestPalindrome(String s) {
    
    
        String str = "";
		int n = s.length();
		if (n != 0)
		{
    
    
			int p1 = 0, p2 = n-1;
			int pp1 = -1, pp2 = -1;
			while (true)
			{
    
    
				while (p1 < p2)
				{
    
    
					if (s.charAt(p1) == s.charAt(p2))
					{
    
    
						if (pp1 == -1 && pp2 == -1)
						{
    
    
							pp1 = p1;
							pp2 = p2;
						}
						p1++;
						p2--;
					}
					else
						break;
				}
				//该子串为回文字符串
				if (p1 >= p2 && pp1 != -1 && pp2 != -1)
					return s.substring(pp1, pp2+1);
				if (p1 >= p2 && pp1 == -1 && pp2 == -1)
					return s.substring(0, 1);
				//由于有不相等的字符退出,记录新的始末位置
				//只能找到右侧的回文子串
				//如果更换两个循环的顺序,则可以找到左侧的子串
				pp1 = -1;
				pp2 = -1;
				while (s.charAt(p1) != s.charAt(p2) && p1 < p2)
					p1++;
				while (s.charAt(p1) != s.charAt(p2) && p1 < p2)
					p2--;
			}
		}
		return str;
    }

思路2

中心扩展算法

  总时间复杂度较高,为O(n2),空间复杂度为O(1)。
  这里要注意边界条件的判断。

public static String longestPalindrome3(String s) {
    
    
		String ret = "";
		int n = s.length();
		int[] a1;
		int[] a2;
		int[] a3;
		int[] tmp;
		int[] MostTmp = {
    
    -1, -1};
		if (n != 0)
		{
    
    
			for (int i = 0; i < n; i++)
			{
    
    
				a1 = getRoundCenter(s, i);
				a2 = getRoundLeft(s, i);
				a3 = getRoundRight(s, i);
				tmp = getMaxRange(a1, getMaxRange(a2, a3)); //当前位置的最大范围数组
				if (tmp[1] - tmp[0] >= MostTmp[1] - MostTmp[0])
					MostTmp = tmp;
			}
			ret = s.substring(MostTmp[0], MostTmp[1]+1);
		}
		return ret;
	}
	
	public static int[] getRoundCenter(String s, int pos) {
    
    
		int[] ret = {
    
    -1, -1};
		int n = s.length();
		if (n >= 0)
		{
    
    
			int i = pos, j = pos; //i向左移,j向右移
			// 可能是因为字符不同退出的,也可能超过边界退出的
			// 这两种情况,归并为相同类型。
			while (i >= 0 && j < n && s.charAt(i) == s.charAt(j))
			{
    
    
				if (s.charAt(i) == s.charAt(j))
				{
    
    
					i--;
					j++;
				}
				else 
					break;
				
			}
			ret[0] = i+1;
			ret[1] = j-1;
		}
		return ret;
	}
	
	public static int[] getRoundLeft(String s, int pos) {
    
    
		int[] ret = {
    
    -1, -1};
		int n = s.length();
		if (n >= 0)
		{
    
    
			int i = pos, j = pos+1;
			int flag = -1;
			while (i >= 0 && j < n)
			{
    
    
				if (s.charAt(i) == s.charAt(j))
				{
    
    
					flag = 1;
					i--;
					j++;
				}
				else 
					break;
			}
			if (flag == 1)
			{
    
    
				ret[0] = i+1;
				ret[1] = j-1;
			}
			else 
			{
    
    
				ret[0] = i;
				ret[1] = i;
			}
			
		}
		return ret;
	}
	
	public static int[] getRoundRight(String s, int pos) {
    
    
		int[] ret = {
    
    -1, -1};
		int n = s.length();
		if (n >= 0)
		{
    
    
			int i = pos-1, j = pos;
			int flag = -1;
			while (i >= 0 && j < n)
			{
    
    
				if (s.charAt(i) == s.charAt(j))
				{
    
    
					flag = 1;
					i--;
					j++;
				}
				else
					break;
				
			}
			if (flag == 1)
			{
    
    
				ret[0] = i+1;
				ret[1] = j-1;
			}
			else
			{
    
    
				ret[0] = j;
				ret[1] = j;
			}
			
		}
		return ret;
	}
	
	public static int[] getMaxRange(int[] a, int[] b)
	{
    
    
		int r1 = a[1] - a[0];
		int r2 = b[1] - b[0];
		if (r1 > r2)
			return a;
		return b;
	}

おすすめ

転載: blog.csdn.net/juttajry/article/details/121397008