lotus

贵有恒何必三更眠五更起 最无益只怕一日曝十日寒

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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 数组和最长回文子串的长度和起始位置。具体的步骤如下:

  1. 初始化一个 n x n 的布尔型数组 dp,其中 n 是字符串的长度。dp[i][j] 表示 s[i…j] 是否是回文串。
  2. 用一个变量 maxLen 记录最长回文子串的长度,初始值为 0。用一个变量 start 记录最长回文子串的起始位置,初始值为 0。
  3. 用一个循环遍历所有可能的子串长度 len,从 1 到 n。
  4. 对于每个 len,用另一个循环遍历所有可能的子串起始位置 i,从 0 到 n - len。
  5. 计算子串结束位置 j = i + len - 1。
  6. 根据 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]。
  7. 如果 dp[i][j] == true,并且 len > maxLen,说明找到了一个更长的回文子串,更新 maxLen 和 start 的值。
  8. 循环结束后,返回 s.substring(start, start + maxLen),这就是最长回文子串。

具体实现

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); // 返回最长回文子串
    }
}

  

3. 总结

posted on 2023-05-01 16:45  白露~  阅读(3)  评论(0编辑  收藏  举报