力扣2131——连接两字母单词得到的最长回文串(贪心+哈希表)

题目(中等)

给你一个字符串数组 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] 仅包含小写英文字母。

思路

看数据范围,1e5,用暴力两两配对尝试必然超时,所以用哈希表分情况计数;
对于叠词,如果成对出现,可以加入答案,如果有单独的,只能在中间多加一个;
对于普通词tmp,能配对的只有它和它回文符串couple,这两个字符串中出现次数最小的min(nomal[tmp], nomal[couple])次数才能配对成功,多余部分不能加入答案。
为避免重复计数,每次加入后清除该字符串的计数

代码

class Solution {
public:
    int longestPalindrome(vector<string>& words) {
        int ans = 0;
        unordered_map<char, int> same;  //存叠词及其出现次数
        unordered_map<string, int> nomal;   //存普通词及其次数
        for(auto word : words) {
            if(word[0] == word[1]) same[word[0]]++;
            else nomal[word]++;
        }
        int flag_same = 0;
        for(auto x : same) {
            if(x.second % 2 == 0) ans += x.second * 2;  //成对叠词可组队
            else {
                flag_same = 1;
                ans += (x.second / 2) * 4;  //偶数部分配对
            }
        }
        ans += flag_same * 2;   //最多允许一个叠词横跨
        for(auto x : nomal) {
            string tmp = x.first;
            if(nomal[tmp] == 0) continue;
            string couple;
            couple.push_back(tmp[1]);
            couple.push_back(tmp[0]);
            ans += min(nomal[tmp], nomal[couple]) * 4;
            nomal[tmp] = 0;
            nomal[couple] = 0;
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值