算法练习第32题-最长回文子串

202 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第16天,点击查看活动详情

一、题目

给你一个字符串 s,找到 s 中最长的回文子串。

示例 1:

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:

输入:s = "cbbd"
输出:"bb"

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/lo… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、思路

  • 思路中心扩散

    • 定义坐标left, right,坐标随for 自增

    • i = 0

    • 定义while left>=0 right < len s[left] == s[right]

    • left = 0 , right = 0, s[left] => b s[rigth] => b

    • 满足条件进入循环,left -- => -1, right = 1,不满足条件退出循环

    • i = 1 left = 1, right = 1, s[left] => a s[right] => a

    • 满足条件 left-- =>0 right++ => 2

    • 再次判断条件 left = 0 right = 2 s[0] => b s[2] => b 满足条件

    • left = -1 rigth = 2, left不满足条件

    • i = 2

    • 再次判断while条件 left = 2, right = 2, s[left] = b s[right] = b

    • left-- => 1 right++ => 3

    • while条件 s[left] = a s[right] = a 满足调条件

    • left-- => 0 right++ => 4

    • while条件 s[left] = b s[right] = d 不满足条件

    • i = 3

    • while条件 left = 3 rigth = 3 s[left] = a s[right] = a

    • left-- => 2 right++ => 4

    • while条件 s[left] = b s[right] = d 不满足条件

    • i = 4

    • while条件 left = 4 right = 4 s[left] = d s[right] = 4

    • left-- => 3 right++ => 5

    • while 条件,rigth < 5 不满足

    • 在这里利用中心扩散把所有的字符串都便利了一遍

    • 当每次遍历,都把数组赋值给result, 每当i加1产生新的left和right时对比下

    • 如果小于result就不再复制到result中

    • 利用substr切割数组,length的长度是right-left-1

    • 然后测试,发现偶数情况下不满足条件

    • 在偶数情况下 left = 0 right = 0+1

    • while s[left] = b s[right] = b

    • left-- => -1 right++ => 2

    • result = s.substr(0, 2) ==> bb

    • i = 1

    • left = 1 right = 2

    • while条件不成立

三、代码

// let s = "babad"
let s = "bb"
let longestPalindrome = function(s) {
  /**
   * 思路中心扩散
   * 
   * 定义坐标left, right,坐标随for 自增
   * i = 0
   * 定义while left>=0 right < len  s[left] == s[right]
   * left = 0 , right = 0, s[left] => b s[rigth] => b
   * 满足条件进入循环,left -- => -1, right = 1,不满足条件退出循环
   * 
   * i = 1 left = 1, right = 1, s[left] => a s[right] => a 
   * 满足条件 left-- =>0 right++ => 2 
   * 再次判断条件 left = 0 right = 2  s[0] => b s[2] => b 满足条件
   * left = -1 rigth = 2, left不满足条件
   * 
   * i = 2
   * 再次判断while条件 left = 2, right = 2, s[left] = b s[right] = b
   * left-- => 1 right++ => 3
   * while条件 s[left] = a s[right] = a 满足调条件
   * left-- => 0 right++ => 4
   * while条件 s[left] = b s[right] = d 不满足条件
   * 
   * i = 3
   * while条件 left = 3 rigth = 3 s[left] = a s[right] = a
   * left-- => 2 right++ => 4 
   * while条件 s[left] = b s[right] = d 不满足条件 
   * 
   * i = 4
   * while条件 left = 4 right = 4 s[left] = d s[right] = 4
   * left-- => 3 right++ => 5
   * while 条件,rigth < 5 不满足
   * 
   * 在这里利用中心扩散把所有的字符串都便利了一遍
   * 当每次遍历,都把数组赋值给result, 每当i加1产生新的left和right时对比下
   * 如果小于result就不再复制到result中
   * 
   * 利用substr切割数组,length的长度是right-left-1
   * 
   * 然后测试,发现偶数情况下不满足条件
   * 
   * 在偶数情况下 left = 0 right = 0+1 
   * while s[left] = b s[right] = b
   * left-- => -1  right++ => 2
   * result =  s.substr(0, 2) ==> bb
   * i = 1
   * left = 1 right = 2
   * while条件不成立
   * 
   * */ 
  //  "babad"
  let result = '', left = 0, right = 0, len = s.length
  for (let i = 0; i < len; i++) {
    let { left:oddl, right:oddR } = oddEvenPalindrome(s, len, i, i)
    left = oddl, right = oddR
    if (result.length < right-left-1) {
      result = s.substr(left+1, right-left-1);
    }
    let { left:evenl, right:evenR } = oddEvenPalindrome(s, len, i, i+1)
    left = evenl, right = evenR
    if (result.length < right-left-1) {
      result = s.substr(left+1, right-left-1)
    }
  }
  return result
}
let oddEvenPalindrome = (s, len, left, right) => {
  while(left >=0 && right < len && s[left]===s[right]) {
    left--
    right++
  }
  return { left, right }
}
longestPalindrome(s)

四、测试用例

image.png