「力扣409」最长回文串

89 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 13 天,点击查看活动详情

背景

笔者最近刷了一道力扣题 最长回文串,略有所悟,分享给掘友🍺

题目

给定一个包含大写字母和小写字母的字符串 s ,返回通过这些字母构造成的 最长的回文串,在构造过程中,请注意 区分大小写 。比如 "Aa" 不能当做一个回文字符串。

示例:

输入: s = "abccccdd"
输出: 7
解释:
我们可以构造的最长的回文串是"dccaccd", 它的长度是 7。

思路

假设回文串叫p,原始字符串叫s

偶数字符

只要是s中出现了偶数次的字符,都可以全部拿到p中,因为以p的中心点中心,把这些偶数字符在两边等量分布,即可形成回文

如:

abbaaacccc 形成最长回文串可以是 aaccbbccaa
aaaaaaccbb 形成最长回文串可以是 aaacbbcaaa

奇数字符

对于 奇数字符,把它减1就能得到该字符最大的偶数次数,那么就跟 偶数字符 一个逻辑了,累加上即可。

最后,如果出现过奇数字符,可以在剩余的奇数字符任意选择 1 个放在 p 的正中间,这不会影响两边已经布好的回文字符,但是注意只能选 1 个奇数字符,但凡多 1 个都会找不到字符和它匹配。

如:

aaabbcc 形成最长回文串可以是 bcaaacb
aabccde 形成最长回文串可以是 acbca

计算方法

所以,总结起来的字符计算方法就是:

偶数次字符个数 + (每种奇数次字符个数-1) * (奇数字符种类) + (出现过奇数字符 ? 1 : 0)

代码

function longestPalindrome(s: string): number {
  // 统计词频
  const map = new Map<string, number>();

  for (let i = 0, len = s.length; i < len; i++) {
    const count = map.get(s[i]);
    map.set(s[i], count ? (count + 1) : 1);
  }

  // 遍历词频表:
  // 1. 偶数词频,直接累加上
  // 2. 奇数词频,减1后累加上
  // 3. 如果出现了奇数,最后累加1
  let showOdd = false;
  let maxLen = 0;
  for (let [_, value] of map) {
    if (value % 2 === 0) {
      maxLen += value;
    }
    else {
      showOdd = true;
      maxLen += (value - 1);
    }
  }

  if (showOdd) {
    maxLen += 1;
  }

  return maxLen;
};

总结

本文是笔者对 最长回文串 这道题的心得感悟,并输出了解题思路和具体的代码,文中涉及数学的 奇数偶数以及它们对回文串的影响,笔者水平有限,不对之处请掘友批评指正~

「保持学习 主动思考 坚持输出」,我是前端涤生,希望这篇文章可以帮到您🍺🍺