Leetcode 5.最长回文子串

给定一个字符串,找到其中最长的回文子串

回文串的定义为左右对称,例如 abcba ,这个字符串以 c 为中心左右对称;又例如 abccba ,这个字符串也是对称的,虽然中心不在某个字符上。

现在假设字符串 str 为 abcdeffeab ,不难看出其中有一个回文子串 abcd effe ab,有假设现在字符串为 abadeffea,里面有两个回文子串 aba d effe a,那么这个字符串的最长回文子串应该为 effe

由于字符串 str 中可能出现多个回文子串,因此,现在假定有两个索引 leftright,表示字符串 str 中索引 left ~ right 的字符子串,现在我们需要判断这个字符子串是否为回文串,只有当str[ left ] = str[ right ]才有可能是回文串,此时有以下几种情况:

  1. left = right,此时这个子串只有一个字符,当然为回文串
  2. left + 1 = right,此时子串有两个字符,且字符相同,比如aa,bb等,这时也是回文串
  3. left + 1 < right,此时字符串有多个字符,因此,这个 left ~ right 子串为回文串当且仅当 left + 1 ~ right - 1 为回文串,假设目前 left ~ right 子串为 abcba,因为 bcb 为回文串,所以 abcba 为回文串;又假设 left ~ right 子串为 abcda,因为 bcd 不为回文串,所以 abcda不为回文串。

因此,使用二维动态规划 dp[i][j] 实现,dp[i][j] = true 字符串从索引 i ~ j的子串为回文串,false表示不是回文串,因此,状态转移方程为:dp[i][j] =

  1. false (str[i] != str[j])
  2. (str[i] = str[j])
    1. true (i = j 或者 i + 1 = j):情况1
    2. true (dp[i + 1][j - 1] = true):情况2
    3. false (其他情况)

代码如下

let longestPalindrome = function(str) {
	
	// 首先初始化dp数组,由于i一定 <= j,因此,将二维数组右上角一半初始化为false
    let dp = new Array(s.length)
    for(let i = 0; i < s.length; i++) {
        dp[i] = new Array(s.length)
    }
    for(let i = 0; i < s.length; i++) {
        for(let j = i; j < s.length; j++) {
            dp[i][j] = false
        }
    }
    
    let maxLen = 0 // 记录当前最长回文子串的长度
    let left = 0 // 当前最长回文子串的左索引
    let right = 0 // 当前最长回文子串的右索引

	// 注意:由于dp[i][j]的值与dp[i + 1][j - 1]的值有关,即此坐标的右上角,因此遍历应为右上往左下
    for(let i = str.length - 1; i >= 0; i--) { 
        for(let j = i; j < str.length; j++) {
            if(s[i] === s[j]) { // 首先得满足str[i] = str[j]
                if(j - i <= 1) { // 情况1
                    dp[i][j] = true
                }
                else if(dp[i + 1][j - 1]) { // 情况2
                    dp[i][j] = true
                }
            }
            if(dp[i][j] && j - i + 1 > maxLen) { // 记录当前最长回文子串的长度以及左右索引
                maxLen = j - i + 1
                left = i
                right = j
            }
        }
    }
    return s.substring(left, right + 1)
};

此时时间复杂度为O(n2),空间复杂度为O(n2)
优化可以考虑使用双指针法可以将空间复杂度降到O(1),后续…

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值