Leecode刷题5. 最长回文子串

给你一个字符串 s,找到 s 中最长的回文子串。

示例 1:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。


示例 2:

输入:s = "cbbd"
输出:"bb"
 

提示:

1 <= s.length <= 1000
s 仅由数字和英文字母组成

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-palindromic-substring/
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

感谢liweiwei1419动态规划、中心扩散、Manacher 算法 labuladong数组双指针直接秒杀七道题目

class Solution {
    public String longestPalindrome(String s) {
//		return longestPalindromeI(s);
//		return longestPalindromeII(s);
		return longestPalindromeIII(s);
	}

	//方法三:动态规划
	//定义dp[i][j]表示子串s[i...j]是否为回文串,根据头尾字符是否相等,需要分类讨论:
	//dp[i][j] = (s[i] == s[j]) and dp[i + 1][j - 1]
	//时间复杂度O(n^2),空间复杂度O(n^2)
	private String longestPalindromeIII(String s) {
		if (s == null || s.length() < 2) {
			return s;
		}
		int len = s.length();
		int maxLen = 1;
		int start = 0;
		boolean[][] dp = new boolean[len][len];
		char[] arr = s.toCharArray();
		for (int i = 0; i < len; i++) {
			dp[i][i] = true;
		}
		for (int j = 1; j < len; j++) {
			for (int i = 0; i < j; i++) {
				if (arr[i] != arr[j]) {
					dp[i][j] = false;
				} else {
					if (j - i <= 2) {
						dp[i][j] = true;
					} else {
						dp[i][j] = dp[i + 1][j - 1];
					}
				}
				// 只要 dp[i][j] == true 成立,就表示子串 s[i..j] 是回文,此时记录回文长度和起始位置
				if (dp[i][j] && j - i + 1 > maxLen) {
					maxLen = j - i + 1;
					start = i;
				}
			}
		}
		return s.substring(start, start + maxLen);
	}

	//方法二:双指针,中心扩散法
	//回文串可能是奇数,也可能是偶数。如果是奇数,则有一个中心字符,否则有两个中心字符
	//定义函数palindrome(s,l,r)表示在s中寻找以s[l]和s[r]为中心的最长回文串
	//遍历每一个下标,以这个下标为中心,利用「回文串」中心对称的特点,往两边扩散,看最多能扩散多远。
	//时间复杂度O(N^2),空间复杂度O(1)
	private String longestPalindromeII(String s) {
		if (s == null || s.length() == 0) {
			return null;
		}
		String res = "";
		for (int i = 0; i < s.length(); i++) {
			//寻找长度为奇数的回文串
			String s1 = palindrome(s, i, i);
			//寻找长度为偶数的回文串
			String s2 = palindrome(s, i, i + 1);
			res = s1.length() > res.length() ? s1 : res;
			res = s2.length() > res.length() ? s2 : res;
		}
		return res;
	}

	private String palindrome(String s, int l, int r) {
		while (l >= 0 && r <= s.length() - 1 && s.charAt(l) == s.charAt(r)) {
			l--;
			r++;
		}
		return s.substring(l + 1, r);
	}

	//方法一:暴力解法,枚举所有长度大于等于2的子串,判断是否满足回文串
	//时间复杂度O(N^3),空间复杂度O(1)
	private String longestPalindromeI(String s) {
		if (s == null || s.length() < 2) {
			return s;
		}
		int start = 0, maxLen = 1;
		int len = s.length();
		char[] arr = s.toCharArray();
		for (int i = 0; i < len - 1; i++) {
			for (int j = i + 1; j < len; j++) {
				if (j - i + 1 > maxLen && validatePalindrome(arr, i, j)) {
					//得到更长的回文子串时,更新 当前子串的起始位置 和 子串长度
					maxLen = j - i + 1;
					start = i;
				}
			}
		}
		return s.substring(start, start + maxLen);
	}

	private boolean validatePalindrome(char[] arr, int i, int j) {
		while (i < j) {
			if (arr[i] != arr[j]) {
				return false;
			}
			i++;
			j--;
		}
		return true;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值