5. 最长回文子串-----还有一种马拉车算法(Manacher 算法)没有展示

5. 最长回文子串

  • 原题链接:
  • 方法一:暴力法
  • 方法二:中心延展法
  • 方法三:动态规划

原题链接:

5. 最长回文子串
https://leetcode.cn/problems/longest-palindromic-substring/

方法一:暴力法

5. 最长回文子串-----还有一种马拉车算法(Manacher 算法)没有展示_第1张图片

package 西湖算法题解___中等题;

public class __5最长回文子串__暴力法 {
	public static void main(String[] args) {

	}//public static void main(String[] args)

	/**
	 *
	 * @param s
	 * @return
	 */
	public String longestPalindrome(String s) {
		if (s.length() <= 1){
			return s;
		}
		//记录最长子串的长度,以及初始位置
		int maxLen = 1,begin = 0;
		//s.charAt(i)每次都会 检查数组下标越界,因此先转换成字符数组,这一步非必需
		char [] charArray_s = s.toCharArray();

		//开始枚举所有长度严格大于1的子串,charArray[i..j]
		for (int i=0;i<s.length()-1;i++){      //这里就是多一个,少一个的问题,不影响
			for (int j = i+1;j<s.length();j++){
				if (j-i+1 >maxLen && isPalindrome(charArray_s,i,j)){
					maxLen = j-i+1;
					begin = i;
				}
			}
		}
		return s.substring(begin,begin+maxLen);

	}//public String longestPalindrome(String s)

	/**
	 *
	 * @param charArray_s
	 * @param left
	 * @param right
	 * @return
	 */
	private boolean isPalindrome(char[] charArray_s, int left, int right) {
		while (left <= right){
			if (charArray_s[left] != charArray_s[right]){
				return false;
			}
			left++;
			right--;
		}
		return true;
	}//private boolean isPalindrome(char[] charArray_s, int i, int j)

}// __5最长回文子串__暴力法

方法二:中心延展法

5. 最长回文子串-----还有一种马拉车算法(Manacher 算法)没有展示_第2张图片

package 西湖算法题解___中等题;

public class __5最长回文子串__中心延展法 {
	public static void main(String[] args) {

	}//public static void main(String[] args)

	/**
	 *
	 * @param s
	 * @return
	 */
	public String longestPalindrome(String s){
		if (s.length() <= 1){
			return s;
		}
		//记录最长子串的长度,以及初始位置
		int maxLen = 1,begin = 0;
		//s.charAt(i)每次都会 检查数组下标越界,因此先转换成字符数组,这一步非必需
		char [] charArray_s = s.toCharArray();
		for (int i=0;i<s.length()-1;i++){
			//假设每个点为中心判断回文子串点
			int oddLen = expandAroundCenter(charArray_s,i,i);   //假设回文子串中心点为奇数
			int evebLen = expandAroundCenter(charArray_s,i,i+1);    //假设回文子串中心点为偶数

			int curMaxLen = Math.max(oddLen,evebLen);
			if (curMaxLen > maxLen){
				maxLen = curMaxLen;
				begin = i-(maxLen-1)/2;
			}
		}
		return s.substring(begin,begin+maxLen);

	}//public String longestPalindrome(String s)

	/**
	 *
	 * @param charArray_s
	 * @param left_center
	 * @param right_center
	 * @return
	 */
	private int expandAroundCenter(char[] charArray_s, int left_center, int right_center) {
		int i = left_center;
		int j = right_center;
		while (i>=0 && j<charArray_s.length){
			if (charArray_s[i] == charArray_s[j]){
				i++;
				j--;
			}else {
				break;
			}
		}
		//不管等不等,都会获取一个中心判断长度
		return j-i-1;
	}
}

方法三:动态规划

状态转移矩阵:

5. 最长回文子串-----还有一种马拉车算法(Manacher 算法)没有展示_第3张图片
5. 最长回文子串-----还有一种马拉车算法(Manacher 算法)没有展示_第4张图片

package 西湖算法题解___中等题;

public class __5最长回文子串__动态规划 {
	public static void main(String[] args) {

	}//public static void main(String[] args)

	/**
	 *
	 * @param s
	 * @return
	 */
	public String longestPalindrome(String s) {
		if (s.length() <= 1){
			return s;
		}
		//记录最长子串的长度,以及初始位置
		int maxLen = 1,begin = 0;
		//s.charAt(i)每次都会 检查数组下标越界,因此先转换成字符数组,这一步非必需
		char [] charArray_s = s.toCharArray();

		//dp[i][j]表示s[i][j]是否是回文串
		boolean dp[][] = new boolean[s.length()][s.length()];
		//先给对角线元素值全部赋值为true
		for (int i=0;i<s.length();i++){
			dp[i][i] = true;
		}
		//注意:从左下角先填,动态规划本质上就是一种用空间换时间的算法
		for (int j=1;j<s.length();j++){
			for (int i=0;i<j;i++){
				if (charArray_s[i] != charArray_s[j]){
					dp[i][j] = false;
				}else {
					//如果只剩两个元素
					if (j-i <3){
						dp[i][j] = true;
					}else {     如果还剩很多个元素
						dp[i][j] = dp[i+1][j-1];
					}
				}

				//只要dp[i][j] == true 成立,就表示子串s[i..j]是回文,此时记录回文长度和起始位置
				//dp[i][j] = dp[i+1][j-1];
				if (dp[i][j] && j-i+1 > maxLen){
					maxLen = j-i+1;
					begin = i;
				}
			}
		}
	return s.substring(begin,begin+maxLen);
	}

}

你可能感兴趣的:(#,LeetCode题解,java学习,算法,java,开发语言)