当前位置: 首页 > news >正文

常见算法题目6 - 给定一个字符串,输出其最长的回文子串

算法题目6 - 给定一个字符串,输出其最长的回文子串

1.问题描述

给定一个字符串,输出其最长的回文子串。
回文串特点:正向遍历输出和逆向遍历输出的结果一致。
例如:fabacaba,最长回文子串为abacaba

输入:fabacaba
输出:abacaba
输入:gfabcdedcbe
输出:bcdedcb

2. 算法解决

2.1 暴力循环法
  • 思路:找到输入字符串的所有子串,判定是否是回文串,如果是回文串,再比较长度,保存最长长度的回文子串。
  • 时间复杂度:O(n^3)
  • 空间复杂度:O(1)
  • 代码如下:
public static String longestPalindrome1(String s) {// 存储结果String result = "";if (s == null || s.isEmpty()) {return result;}if (s.length() < 2) {return s;}// 存储长度int maxLength = 0;for (int i = 0; i < s.length(); i++) {for (int j = i + 1; j < s.length() + 1;j++) {String substring = s.substring(i, j);// 判断是否是回文if (isPalindrome(substring) && substring.length() > maxLength) {result = substring;maxLength = substring.length();}}}return result;}/*** 判断是否是回文* @param str* @return*/public static boolean isPalindrome(String str) {for (int i = 0;i < str.length() / 2; i++) {if (str.charAt(i) != str.charAt(str.length() - i - 1)) {return false;}}return true;}
2.2 中心扩展法(最优解)
  • 思路:假设中心为某个字符或者某个字符和它右边的字符,通过扩展判断该字符序列是否为回文串。 处理奇偶长度回文,以单个字符为中心(奇),或以两个字符中间点为中心(偶)。
  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1)
  • 代码如下:
public static String longestPalindrome2(String s) {String result = "";if (s == null || s.length() < 1) {return "";}for (int i = 0; i < s.length(); i++) {// 奇数回文子串String str1 = dealOddOrEvenNumberStr(s, i, i);// 偶数回文子串String str2 = dealOddOrEvenNumberStr(s, i, i + 1);result = result.length() > str1.length() ? result : str1;result = result.length() > str2.length() ? result : str2;}return result;}/*** 奇偶回文子串处理* @param s* @param left* @param right* @return*/private static String dealOddOrEvenNumberStr(String s, int left, int right) {while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {left--;right++;}return s.substring(left + 1, right);}
2.3 动态规划法
  • 思路:动态规划算法,最重要的是找到边界和动态转移方程。
    ①定义状态:dp[i][j]表示s[i…j]是否是回文串,标识字符串s从i到j是否是回文串(左闭右闭)。
    ②边界和状态转移方程:
    • dp[i][j] = true 当 i == j(单字符) 例如:a
    • dp[i][j] = (s[i]==s[j]) 当 j-i ==1(双字符) 例如:aa
    • dp[i][j] = (s[i]==s[j]) && dp[i+1][j-1](多字符)例如:aba

③dp[i][j] = (s[i]==s[j]) && dp[i+1][j-1]解释:
假设现在的回文字符串为 abcba,i = 0, j=4, dp[i][j] = true,s[i] = s[j] = a。
那么去掉i、j上的两个字符后,就是bcb,仍然是一个回文串,相比于原来的字符串,i1 = 1 = i+1, j1 = 3 = j-1。
dp[i][j]为回文串的话,必须满足i <= j ,所以可以得出 i+1 <= j-1 —> j-i >= 2 ,即得 j-i < 2不能为状态转移方程求得,可以得出 dp[i][j]只有一个字符或者空串的情况,即是s[i] = s[j]时,一个字符的和空串一定是个回文串。

  • 时间复杂度:O(n^2)
  • 空间复杂度:O(n^2)
  • 代码如下:
public static String longestPalindromeDP3(String s) {if (s == null) {return "";}// 获取字符串长度int length = s.length();if (length < 2) {return s;}// 初始化dp数组boolean[][] dp = new boolean[length][length];// 初始化边界条件,单字符,肯定是回文串for (int i = 0; i < length; i++) {dp[i][i] = true;}// 回文最大长度 初始化为1 即默认单字符为回文串int maxLength = 1;// 回文起始位置int maxStart = 0;// 枚举子串的长度for (int len = 2; len <= length; len++) {for (int i = 0; i < length - len + 1; i++) {// 子串的结束位置int j = i + len - 1;// 判断是否为回文串if (s.charAt(i) == s.charAt(j)) {// 如果是回文串if (len == 2 || dp[i + 1][j - 1]) {// 更新回文串的起始位置和长度dp[i][j] = true;if (len > maxLength) {maxLength = len;maxStart = i;}}}}}// 返回最长回文子串return s.substring(maxStart, maxStart + maxLength);}
}

3. 测试

调用测试:

public class HwTest {public static void main(String[] args) {String s = "gfabcdedcbe";String result1 = longestPalindrome1(s);System.out.println("最长回文子串,暴力循环法结果:" + result1);System.out.println("=====================");String result2 = longestPalindrome2(s);System.out.println("最长回文子串,中心扩展法结果:" + result2);System.out.println("=====================");String result3 = longestPalindromeDP3(s);System.out.println("最长回文子串,动态规划_优化结果:" + result3);}}
  • 暴力循环法输出结果:
    在这里插入图片描述
  • 中心扩展法输出结果:
    在这里插入图片描述
  • 动态规划法输出结果:
    在这里插入图片描述
http://www.xdnf.cn/news/971317.html

相关文章:

  • F5 BIG IP show running config
  • 模型参数、模型存储精度、参数与显存
  • Postman参数化详解
  • leetcode_35.搜索插入位置
  • 如何查看电脑系统的初始安装时间?
  • 龙虎榜——20250610
  • 【沉浸式求职学习day53】【Spring】
  • MFC 第一章概述
  • 2025 Java 面试大全
  • 39.第二阶段x64游戏实战-封包-分析计数器
  • gro文件和top文件介绍,以及如何合并两个gro文件或两个top文件
  • 【论文解读】ReSearch:让LLM自主学习搜索
  • Qt进阶开发:动画框架的介绍和使用
  • Zynq multi boot及网口远程更新开发
  • Android Studio 问题:Android Studio 一直开在 Updating indexes
  • 【运维】【期末实训】网站简易搭建模拟
  • 核心机制:面向字节流
  • C++:std::is_convertible
  • <7>-MySQL内置函数
  • Python训练营-Day27-函数专题2:装饰器
  • Java如何权衡是使用无序的数组还是有序的数组
  • copilot基于 DeepSeek-R1 思路构建 VLA 自动驾驶强化学习系统
  • 华为云Flexus+DeepSeek征文|体验华为云ModelArts快速搭建Dify-LLM应用开发平台并创建联网大模型
  • QMC5883L的驱动
  • iview组件库:自定义方法去控制Tree树形数据的根节点与叶节点的关联性
  • Android Studio jetpack compose折叠日历日期选择器【折叠日历】
  • IOC和AOP
  • vue实现气泡词云图
  • FastJson的反序列化问题入门
  • Qt使用ODBC连接MySQL数据库