python最长回文子串leetcode_leetcode解题系列-最长回文子串最全解法

本人是一个一名前端菜:chicken:,正在努力加班加点学习中,看着大佬们写的文章、demo啥的,羡慕不已。盼望着大佬们哪天能给个内推机会啥的那就nice了。 最近刷leetcode刷到这个题目,也在网上看到了各种各样的解法,于湿乎我也尝试着写文章,记录一下学习中值得分享的内容

第一次写文章,有不当之处还望各位大佬指出。

问题描述

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:

输入: “babad”

输出: “bab”

注意: “aba” 也是一个有效答案。

示例 2:

输入: “amnbvcxzzxcvbnmb”

输出: “mnbvcxzzxcvbnm”

分析与求解

第一种 暴力解法

最容易想到的就是暴力解法,即外面的两层循环找到所有子串,第三层循环判断子串是否是回文。方法的时间复杂度为O(n^3),空间复杂度为O(1)。

var longestPalindrome = function (s) {

let n = s.length;

if(n == 0) return ''; //字符串为空则返回空

if(n == 1) return s; //字符串为一个字符, 显然返回自身

let result = ''

for (let i = 0; i < n; i++) { //字符串长度超过2

for (let j = i + 1; j <= n; j++) {

let str = s.slice(i, j); //可得到所有子串

let f = str.split('').reverse().join(''); //对字符串利用数组方法倒序

if (str == f) { //判断是否为回文

result = str.length > result.length ? str : result;

}

}

}

return result;

}

console.log(longestPalindrome(str))

复制代码

很显然,此解法虽然最终能够得到结果,但是效率很低,在这个讲究高效编程的时代,这种方法是不可取的。

(此方法由于时间复杂度太高,在leetcode上提交时会提示 Time Limit Exceeded,并且提交不了)

第二种 动态规划

动态规划(Dynamic Programming)是一种分阶段求解决策问题的数学思想。总结起来就是一句话,大事化小,小事化了。

能采用动态规划求解的问题的一般要具有3个性质:

1.最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。

2.无后效性:即某阶段状态一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与当前状态有关。

3.有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。(该性质并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法相比就不具备优势

大概了解了一下动态规划,下面让我们来看具体代码

var longestPalindrome = function(s) {

let len = s.length;

let result;

let i,j,L;

let dp=Array(len).fill(0).map(x=>Array(len).fill(0));

//console.log(dp);

if(len<=1){

return s

}

// 只有一个字符的情况是回文

for(i = 0;i

dp[i][i] = 1

result = s[i]

}

// L是i和j之间的间隔数(因为间隔数从小到大渐增,所以大的间隔数总能包含小的间隔数)

// i j

// abcdcba.length = L 所以 L = j-i+1; => j = i+L-1;

for ( L = 2; L <= len; L++) {

// 从0开始

for ( i = 0; i <= len - L; i++) {

j = i + L - 1;

if(L == 2 && s[i] == s[j]) {

dp[i][j] = 1;

result = s.slice(i, i + L);

}else if(s[i] == s[j] && dp[i + 1][j - 1] == 1) {

dp[i][j] = 1

result = s.slice(i, i + L);

}

}

}

//console.log(result);

return result;

}

复制代码

方法的时间复杂度为O(n^2), 时间复杂度也为O(n^2), 效率上总体来说相对暴力解法有很大的提升, 是一种不错的解法, 而且动态规划的应用场景很多, 想进一步学习的老铁可以点这里动态规划应用场景。

第三种 Manacher算法

Manacher算法,又叫“马拉车”算法,可以在时间复杂度为O(n)的情况下求解一个字符串的最长回文子串长度的问题。

在进行Manacher算法时,字符串都会进行上面的进入一个字符处理,比如输入的字符为acbbcbds,用“#”字符处理之后的新字符串就是#a#c#b#b#c#b#d#s#。

var str = 'ddabbade'

const longestPalindrome = function (s) {

if (s.length == 1) {

return s

}

let str = '#' + s.split('').join('#') + '#'

let rl = []

let mx = 0

let pos = 0

let ml = 0

for (let i = 0; i < str.length; i++) {

if (i < mx) {

rl[i] = Math.min(rl[2 * pos - i], mx - i)

} else {

rl[i] = 1

}

while (i - rl[i] > 0 && i + rl[i] < str.length && str[i - rl[i]] == str[i + rl[i]]) {

rl[i]++

}

if (rl[i] + i - 1 > mx) {

mx = rl[i] + i - 1

pos = i

}

if (ml < rl[i]) {

ml = rl[i]

sub = str.substring(i - rl[i] + 1, i + rl[i])

}

}

return sub.split('#').join('').trim()

}

console.log(longestPalindrome(str)) //输出dabbad

复制代码

该方法的时间复杂度为O(n),效率相对前两种方法有巨大的提升。有一篇大佬的文章有助于大家对Manacher算法的理解Manacher算法详解

总结

这三种方法是最长回文子串的最常用解法。 暴力解法最容易理解也是最简单,但是算法效率低下。 动态规划对暴力解法做了一定的改进,它避免了在验证回文时进行不必要的重复计算。 而Manacher算法则是此题效率最高的算法,虽然相对前两种方法稍微难理解一点,但是仔细看看也OK啦:smile:。 大家如果还有什么更优的解法,欢迎评论区见:smile:

最后容许小生附上我的github地址

里面记录了我学习前端的点点滴滴,觉得有帮助的小哥哥小姐姐可以给个小星星哟:smile:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据提供的引用内容,有三种方法可以解决LeetCode上的最长回文子串问题。 方法一是使用扩展中心法优化,即从左向右遍历字符串,找到连续相同字符组成的子串作为扩展中心,然后从该中心向左右扩展,找到最长的回文子串。这个方法的时间复杂度为O(n²)。\[1\] 方法二是直接循环字符串,判断子串是否是回文子串,然后得到最长回文子串。这个方法的时间复杂度为O(n³),效率较低。\[2\] 方法三是双层for循环遍历所有子串可能,然后再对比是否反向和正向是一样的。这个方法的时间复杂度也为O(n³),效率较低。\[3\] 综上所述,方法一是解决LeetCode最长回文子串问题的最优解法。 #### 引用[.reference_title] - *1* [LeetCode_5_最长回文子串](https://blog.csdn.net/qq_38975553/article/details/109222153)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Leetcode-最长回文子串](https://blog.csdn.net/duffon_ze/article/details/86691293)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [LeetCode 第5题:最长回文子串Python3解法)](https://blog.csdn.net/weixin_43490422/article/details/126479629)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值