返回介绍

solution / 2100-2199 / 2131.Longest Palindrome by Concatenating Two Letter Words / README

发布于 2024-06-17 01:03:09 字数 4121 浏览 0 评论 0 收藏 0

2131. 连接两字母单词得到的最长回文串

English Version

题目描述

给你一个字符串数组 words 。words 中每个元素都是一个包含 两个 小写英文字母的单词。

请你从 words 中选择一些元素并按 任意顺序 连接它们,并得到一个 尽可能长的回文串 。每个元素 至多 只能使用一次。

请你返回你能得到的最长回文串的 长度 。如果没办法得到任何一个回文串,请你返回 0 。

回文串 指的是从前往后和从后往前读一样的字符串。

 

示例 1:

输入:words = ["lc","cl","gg"]
输出:6
解释:一个最长的回文串为 "lc" + "gg" + "cl" = "lcggcl" ,长度为 6 。
"clgglc" 是另一个可以得到的最长回文串。

示例 2:

输入:words = ["ab","ty","yt","lc","cl","ab"]
输出:8
解释:最长回文串是 "ty" + "lc" + "cl" + "yt" = "tylcclyt" ,长度为 8 。
"lcyttycl" 是另一个可以得到的最长回文串。

示例 3:

输入:words = ["cc","ll","xx"]
输出:2
解释:最长回文串是 "cc" ,长度为 2 。
"ll" 是另一个可以得到的最长回文串。"xx" 也是。

 

提示:

  • 1 <= words.length <= 105
  • words[i].length == 2
  • words[i] 仅包含小写英文字母。

解法

方法一:贪心 + 哈希表

我们先用哈希表 cnt 统计每个单词出现的次数。

遍历 cnt 中的每个单词 $k$ 以及其出现次数 $v$:

如果 $k$ 中两个字母相同,那么我们可以将 $\left \lfloor \frac{v}{2} \right \rfloor \times 2$ 个 $k$ 连接到回文串的前后,此时如果 $k$ 还剩余一个,那么我们可以先记录到 $x$ 中。

如果 $k$ 中两个字母不同,那么我们要找到一个单词 $k'$,使得 $k'$ 中的两个字母与 $k$ 相反,即 $k' = k[1] + k[0]$。如果 $k'$ 存在,那么我们可以将 $\min(v, cnt[k'])$ 个 $k$ 连接到回文串的前后。

遍历结束后,如果 $x$ 不为空,那么我们还可以将一个单词连接到回文串的中间。

时间复杂度 $O(n)$,空间复杂度 $O(n)$。其中 $n$ 为 words 的长度。

class Solution:
  def longestPalindrome(self, words: List[str]) -> int:
    cnt = Counter(words)
    ans = x = 0
    for k, v in cnt.items():
      if k[0] == k[1]:
        x += v & 1
        ans += v // 2 * 2 * 2
      else:
        ans += min(v, cnt[k[::-1]]) * 2
    ans += 2 if x else 0
    return ans
class Solution {
  public int longestPalindrome(String[] words) {
    Map<String, Integer> cnt = new HashMap<>();
    for (var w : words) {
      cnt.put(w, cnt.getOrDefault(w, 0) + 1);
    }
    int ans = 0, x = 0;
    for (var e : cnt.entrySet()) {
      var k = e.getKey();
      var rk = new StringBuilder(k).reverse().toString();
      int v = e.getValue();
      if (k.charAt(0) == k.charAt(1)) {
        x += v & 1;
        ans += v / 2 * 2 * 2;
      } else {
        ans += Math.min(v, cnt.getOrDefault(rk, 0)) * 2;
      }
    }
    ans += x > 0 ? 2 : 0;
    return ans;
  }
}
class Solution {
public:
  int longestPalindrome(vector<string>& words) {
    unordered_map<string, int> cnt;
    for (auto& w : words) cnt[w]++;
    int ans = 0, x = 0;
    for (auto& [k, v] : cnt) {
      string rk = k;
      reverse(rk.begin(), rk.end());
      if (k[0] == k[1]) {
        x += v & 1;
        ans += v / 2 * 2 * 2;
      } else if (cnt.count(rk)) {
        ans += min(v, cnt[rk]) * 2;
      }
    }
    ans += x ? 2 : 0;
    return ans;
  }
};
func longestPalindrome(words []string) int {
  cnt := map[string]int{}
  for _, w := range words {
    cnt[w]++
  }
  ans, x := 0, 0
  for k, v := range cnt {
    if k[0] == k[1] {
      x += v & 1
      ans += v / 2 * 2 * 2
    } else {
      rk := string([]byte{k[1], k[0]})
      if y, ok := cnt[rk]; ok {
        ans += min(v, y) * 2
      }
    }
  }
  if x > 0 {
    ans += 2
  }
  return ans
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文