lotus

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

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  1846 随笔 :: 0 文章 :: 109 评论 :: 288万 阅读

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),这就是最长回文子串。

具体实现

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

  

3. 总结

posted on   白露~  阅读(5)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享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)
点击右上角即可分享
微信分享提示