1. 题目
读题
https://leetcode.cn/problems/longest-palindromic-substring/description/
考查点
- 这道题的考查点是动态规划的基本思想和技巧,以及字符串的操作和判断。
2. 解法
思路
- 动态规划的思路是,用一个二维数组 dp[i][j] 表示字符串从 i 到 j 是否是回文串,然后遍历所有可能的子串,更新 dp 数组和最长回文子串的长度和起始位置。
- 动态规划的状态转移方程是:
- 如果 len == 1,那么 dp[i][j] = true。
- 如果 len == 2,那么 dp[i][j] = s.charAt(i) == s.charAt(j)。
- 如果 len > 2,那么 dp[i][j] = s.charAt(i) == s.charAt(j) && dp[i + 1][j - 1]。
- 动态规划的遍历顺序是,先遍历子串长度 len,从 1 到 n,然后遍历子串起始位置 i,从 0 到 n - len。
- 这道题的考查点是动态规划的基本思想和技巧,以及字符串的操作和判断。
- 动态规划是一种将复杂问题分解为子问题,然后利用子问题的解来求解原问题的方法。动态规划通常需要找到一个合适的状态表示和状态转移方程,以及一个合理的遍历顺序。
- 字符串的操作和判断是指如何获取字符串的长度,如何访问和比较字符串的字符,如何截取字符串的子串等。这些都是编程中常用的技能,需要熟练掌握。
代码逻辑
这个代码的思路是,用一个二维数组 dp[i][j] 表示字符串从 i 到 j 是否是回文串,然后遍历所有可能的子串,更新 dp 数组和最长回文子串的长度和起始位置。具体的步骤如下:
- 初始化一个 n x n 的布尔型数组 dp,其中 n 是字符串的长度。dp[i][j] 表示 s[i…j] 是否是回文串。
- 用一个变量 maxLen 记录最长回文子串的长度,初始值为 0。用一个变量 start 记录最长回文子串的起始位置,初始值为 0。
- 用一个循环遍历所有可能的子串长度 len,从 1 到 n。
- 对于每个 len,用另一个循环遍历所有可能的子串起始位置 i,从 0 到 n - len。
- 计算子串结束位置 j = i + len - 1。
- 根据 len 的不同,判断 s[i…j] 是否是回文串,并更新 dp[i][j] 的值。
- 如果 len == 1,那么 s[i…j] 只有一个字符,一定是回文串,所以 dp[i][j] = true。
- 如果 len == 2,那么 s[i…j] 只有两个字符,需要判断它们是否相等,所以 dp[i][j] = s.charAt(i) == s.charAt(j)。
- 如果 len > 2,那么 s[i…j] 有多个字符,需要判断首尾字符是否相等,并且去掉首尾字符后的子串是否是回文串,所以 dp[i][j] = s.charAt(i) == s.charAt(j) && dp[i + 1][j - 1]。
- 如果 dp[i][j] == true,并且 len > maxLen,说明找到了一个更长的回文子串,更新 maxLen 和 start 的值。
- 循环结束后,返回 s.substring(start, start + maxLen),这就是最长回文子串。
具体实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | class Solution { public String longestPalindrome(String s) { int n = s.length(); boolean [][] dp = new boolean [n][n]; // dp[i][j] 表示 s[i..j] 是否是回文串 int maxLen = 0 ; // 最长回文子串的长度 int start = 0 ; // 最长回文子串的起始位置 for ( int len = 1 ; len <= n; len++) { // 遍历所有可能的子串长度 for ( int i = 0 ; i < n - len + 1 ; i++) { // 遍历所有可能的子串起始位置 int j = i + len - 1 ; // 子串结束位置 if (len == 1 ) { // 长度为 1 的子串一定是回文串 dp[i][j] = true ; } else if (len == 2 ) { // 长度为 2 的子串需要判断两个字符是否相等 dp[i][j] = s.charAt(i) == s.charAt(j); } else { // 长度大于 2 的子串需要判断两端字符是否相等,并且去掉两端字符后的子串是否是回文串 dp[i][j] = s.charAt(i) == s.charAt(j) && dp[i + 1 ][j - 1 ]; } if (dp[i][j] && len > maxLen) { // 如果当前子串是回文串,并且长度大于之前的最大长度,更新最大长度和起始位置 maxLen = len; start = i; } } } return s.substring(start, start + maxLen); // 返回最长回文子串 } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
2019-05-01 java中的12种锁
2019-05-01 公平锁与非公平锁
2019-05-01 设计模式:门面模式(Facade)
2019-05-01 设计模式:装饰者模式
2019-05-01 设计模式:组合模式
2019-05-01 设计模式:桥接模式
2019-05-01 设计模式:适配器模式(Adapter)