JS获取字符串里最长的回文字符串

方法一

使用双指针配合枚举

/**
 * @param {string} s
 * @return {string}
 */
const longestPalindrome = s => {
  const LEN = s.length
  if (LEN < 2) {
    return s
  }
  let maxStr = ''
  /**
   * @param left 
   * @param right 
   * @returns 
   */
  const findPalindrome = (left, right) => {
    while (left >= 0 && right < LEN && s[left] === s[right]) {
      left--
      right++
    }
    return s.substring(left + 1, right)
  }
  for (let i = 0; i < LEN; i++) {
    // 以i为中心判断是否是回文,如果回文是偶数则i和i+1为中心,负责i为中心。
    const strOdd = findPalindrome(i, i)
    const strEven = findPalindrome(i, i + 1)
    if (strEven.length > maxStr.length) {
      maxStr = strEven
    }
    if (strOdd.length > maxStr.length) {
      maxStr = strOdd
    }
  }
  return maxStr
}

方法二

动态规划+枚举

/**
 * @param {string} s 
 */
const longestPalindrome1 = s => {
  const LEN = s.length
  if (LEN < 2) {
    return s
  }
  // 需要保证s[l]到s[r]为回文则s[l-1]到s[r+1]也是回文,通过二维数组记录lr的回文
  const dp = []
  for (let i = 0; i < LEN; i++) {
    dp[i] = new Array(LEN).fill(false)
    dp[i][i] = true
  }
  let maxStr = s[0]
  for (let palindromeLen = 2; palindromeLen <= LEN; palindromeLen++) {
    for (let l = 0; l < LEN; l++) {
      // 右指针指向的位置应该为左指针加回文串长度减一
      let r = l + palindromeLen - 1
      if (r >= LEN) {
        break
      }
      if (s[l] === s[r]) {
        // 左指针与右指针中间最多为1个的时候可以直接判定为true, ABA 或者 aa
        if (r - l <= 2) {
          dp[l][r] = true
        } else {
          dp[l][r] = dp[l + 1][r - 1]
        }
      } else {
        dp[l][r] = false
      }

      if (dp[l][r] && r - l + 1 > maxStr.length) {
        maxStr = s.substring(l, r + 1)
      }
    }
  }
  return maxStr
}

方法三

动态规划+双指针
在这里插入图片描述
s[l][r] 依赖 s[l+1][r-1],说明是依赖上层,所以需要把上层填满,所以r需要递增遍历固定r动l,且l需要小于r,相等的时候在初始化已经做好了。

  const LEN = s.length
  if (LEN < 2) {
    return s
  }
  // 需要保证s[l]到s[r]为回文则s[l-1]到s[r+1]也是回文,通过二维数组记录lr的回文
  const dp = []
  for (let i = 0; i < LEN; i++) {
    dp[i] = new Array(LEN).fill(false)
    dp[i][i] = true
  }
  let start = 0 , end = 0;
  // l必须小于r从第一层填起可以画三角,s[l]到s[r]依赖s[l-1]到s[r+1]
  for (let r = 1; r < LEN; r++) {
    for (let l = r - 1; l >= 0; l--) {
      if (s[l] === s[r]) {
        // 左指针与右指针中间最多为1个的时候可以直接判定为true, ABA 或者 aa
        if (r - l <= 2) {
          dp[l][r] = true
        } else {
          dp[l][r] = dp[l + 1][r - 1]
        }
      } else {
        dp[l][r] = false
      }

      if (dp[l][r] && r - l > end - start) {
        end = r;
        start = l;
      }
    }
  }
  return s.slice(start,end+1)

说明

方法一和方法二都可以采用start和end来记位置,最后再去拿到回文字符串。这样减少对字符串的截取,时间会更快。方法一如果记位置则需要改造获取回文的方法并且直接在回文内部去更新start和end。

  • 10
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值