LeetCode回文问题总结,回文子串,回文子序列等

这篇博客总结了LeetCode中关于回文的几道经典问题,包括最长回文子串、回文子串个数、最长回文子序列等。通过中心扩展、动态规划和回溯等方法,探讨了解决这类问题的思路和技巧。还涵盖了回文数的判断以及如何分割回文串。
摘要由CSDN通过智能技术生成

1. LeetCode 5. 最长回文子串(求长度)

传送门

题目: 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设s 的最大长度为 1000。
输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。

假设字符串s的长度为length,建立一个length*length的矩阵dp。令 dp[i][j] 表示 S[i] 至 S[j] 所表示的子串是否是回文子串。

  1. 当 i == j,dp[i][j] 是回文子串(单字符都是回文子串);
  2. 当 j - i < 3,只要 S[i] == S[j],则 dp[i][j] 是回文子串(如"aa",“aba”),否则不是;
  3. 当 j - i >= 3,如果 S[i] == S[j] && dp[i+1][j-1] ,则 dp[i][j] 是回文子串,否则不是 。
    在这里插入图片描述

需要注意的点是,因为要访问dp[i+1][j-1],因此 i 是从大到小的,j是从小到大的。

public String longestPalindrome(String s) {
   
    int len = s.length();
    if (len == 0) return "";
    boolean[][] dp = new boolean[len][len];
    int left = 0, right = 0, ans = 0;// left right 记录最长的回文子串起始索引

    for (int i = len - 1; i >= 0; --i) {
    
        dp[i][i] = true;
        for (int j = i + 1; j < len; ++j) {
   
            if (s.charAt(i) == s.charAt(j))  {
   
                if (j - i < 3) 
                    dp[i][j] = true;
                else 
                    dp[i][j] = dp[i + 1][j - 1];
            }
            if (dp[i][j] == true && j - i > right - left) {
   
                right = j;
                left = i;
            }
        }
    }
    return s.substring(left, right + 1);
}

时间空间都是 O(n*n)马拉车算法是O(n) 。

不用考虑dp[i + 1][j - 1] 的索引越界的情况,因为只有两种情况会越界:
i =len-1 或者 j=0;

  1. i=len-1 时, j=i,也从len-1 开始,但是 if里第一个条件j-i<=2已经满足,不会访问dp[i+1], 而且j层的循环只执行一次(j++之后等于len)就退出了。

  2. j=0时,因为j从i开始增大,所以i也是0,同样 if 的第一个条件也满足了。


2. LeetCode 647. 回文子串(求个数)

传送门

题目:给定一个字符串,你的任务是计算这个字符串中有多少个回文子串。
具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被计为是不同的子串。

示例 1: 输入: “abc” 输出: 3
解释: 三个回文子串: “a”, “b”, “c”.
示例 2: 输入: “aaa” 输出: 6
说明: 6个回文子串: “a”, “a”, “a”, “aa”, “aa”, “aaa”.

方法1. 中心扩展
	int countSubstrings(string s) {
   
        int ans = 0;
        for (int i = 0; i < s.length(); ++i) {
   
            ans += helper(s, i, i); //以当前点i位置,向两边扩展
            ans += helper(s, i, i + 1);// 以i i+1位置向两边扩展
        }
        return ans;
     }

    int helper(string s, int<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值