最长回文数字

中心扩散

中心扩散就是从中心往外逐层扩散。以单个字符往两边扩散,如果两边字符相等则是回文串。扩散又分两种情况 分别是以该字符为中心,和以该字符和下一个字符的空隙为中心

let longestPalindrome2 = function (s) {
    const n = s.length
    if (n == 1) return s
    let start = 0,
        end = 0;
    const expandFcn = (left, right) => {
        while (left >= 0 && right < n && s[left] == s[right]) {
            --left;
            ++right;
        }
        return right - left - 1
    }
    for (let i=0; i < n; i++) {
        // 找到从s[i]向外扩散长度len是最长回文数字
        // 两种可能性,一个是s[i],一个是s[i]后面的间隙
        let len = Math.max(expandFcn(i, i), expandFcn(i, i + 1))
        console.log(i, len, 'len');
        if (len > (end - start)) {
        	// i为回文数字的中心下标,(len-1)/2是拿到回文数字的左边长度
        	// len-1的目的是为了保证拿到的是最小长度,len=4,那么取到的是1,len=5,那么取到的是2
            start = i - parseInt((len - 1) / 2) 
            end = i + parseInt(len / 2) // 回文数字的右下标
        }
    };
    return s.substring(start, end + 1)
};

动态规划

用一个二维数组存放结果,dp[i][j]指的是从下标i到下标j组成的字符串
如果字符串首尾字符相同且去除首尾的子串也为回文串 那么 该字符串必定为回文串。
那么首先 所有长度为1的 单个字符都为回文。
然后从长度为2开始依次遍历每个长度下的子串 ,并记录该子串是否为回文。
由于长度是从短到长,也就是遍历到的字符串其去除首尾的子串必定已经得到判断。
所以只需要判断该串的首尾字符是否相等以及其子串是否为回文即可判断该串是否为回文串。
如果是回文串记录其长度即可

function longestPalindrome(s) {
  if(s.length <= 1) return s;
  let begin = 0,
    max = 1,
    j = 0,
    n = s.length,
    dp = [];
  for (let i = 0; i < n; i++) {
    dp[i] = new Array(n).fill(true);
  }
  for (let L = 2; L <= n; L++) {
    for (let i = 0; i < n; i++) {
      j = i + L - 1;
      if (j >= n) break;
      if (s[i] !== s[j]) {
        dp[i][j] = false;
      } else {
        if (j - i <= 2) {
          dp[i][j] = true;
        } else {
          dp[i][j] = dp[i + 1][j - 1]
        }
      }
      if (dp[i][j] && (j-i+1)>max) {
        begin = i;
        max = j-i+1;
      }
    }
  }
  return s.substr(begin, max)
}
console.log(longestPalindrome("bba"))

你可能感兴趣的:(面试,算法,前端,javascript,vue.js,html,笔记)