AcWing
  • 首页
  • 课程
  • 题库
  • 更多
    • 竞赛
    • 题解
    • 分享
    • 问答
    • 应用
    • 校园
  • 关闭
    历史记录
    清除记录
    猜你想搜
    AcWing热点
  • App
  • 登录/注册

LeetCode 336. Palindrome Pairs    原题链接    困难

作者: 作者的头像   yxc ,  2018-06-28 21:01:21 ,  所有人可见 ,  阅读 1885


10


4

题目描述

给定一个单词数组,不包含相同单词。请找出所有的下标对(i, j),满足words[i] + words[j] 是回文串。

样例1

给定 words = ["bat", "tab", "cat"]
返回 [[0, 1], [1, 0]]
解释:这两个回文串分别是 ["battab", "tabbat"]

样例2

给定 words = ["abcd", "dcba", "lls", "s", "sssll"]
返回 [[0, 1], [1, 0], [3, 2], [2, 4]]
解释:这4个回文串分别是 ["dcbaabcd", "abcddcba", "slls", "llssssll"]

算法

(回文串,哈希表) $O(nL^2)$

首先,我们先来分析一下两个单词组成的回文串有什么性质。如下图所示:
QQ图片20180628205310.png
ac和cd分别表示两个单词,不妨假设cd较短。我们在线段中找到b点,使得 $l_{ab} = l_{cd}$。
则ad为回文串,等价于ab和cd的逆序相等,且bc是回文串。

所以我们可以将所有单词的逆序存入哈希表,然后先枚举每个单词,再枚举每个单词的b点的位置,然后在哈希表中查找是否存在一个单词和ab相等,且bc是回文串,如果是 true,则找到了一组解。

时间复杂度分析:令 $n$ 表示单词个数,$L$ 表示单词的平均长度。枚举单词的计算量是 $O(n)$,对每个单词枚举b点的位置的计算量是 $O(L)$,判断回文串的计算量是 $O(L)$,所以总时间复杂度是 $O(nL^2)$。

C++ 代码

class Solution {
public:
    vector<vector<int>> palindromePairs(vector<string>& words) {
        unordered_map<string, int> S;
        for (int i = 0; i < words.size(); i ++ )
        {
            string key = words[i];
            reverse(key.begin(), key.end());
            S[key] = i;
        }
        vector<vector<int>> res;
        if (S.count(""))
        {
            for (int i = 0; i < words.size(); i ++ )
                if (words[i] != "" && is_palindrome(words[i]))
                    res.push_back({S[""], i});
        }
        for (int i = 0; i < words.size(); i ++ )
            for (int j = 0; j < words[i].size(); j ++ )
            {
                string left = words[i].substr(0, j);
                string right = words[i].substr(j);
                if (S.count(left) && is_palindrome(right) && S[left] != i) res.push_back({i, S[left]});
                if (S.count(right) && is_palindrome(left) && S[right] != i) res.push_back({S[right], i});
            }
        return res;
    }

    bool is_palindrome(string &word)
    {
        for (int i = 0, j = word.size() - 1; i < j; i ++ , j -- )
            if (word[i] != word[j])
                return false;
        return true;
    }
};

4 评论


用户头像
aerpeisi   2025-06-05 16:14 · 北京      1    踩      回复

这优化了什么

用户头像
aerpeisi   2025-06-05 16:39 · 北京      1    踩      回复

我没看错的话,优化前后好像没什么区别


用户头像
aerpeisi   2025-06-05 16:16 · 北京         踩      回复
        if (S.count(""))
        {
            for (int i = 0; i < words.size(); i ++ )
                if (words[i] != "" && is_palindrome(words[i]))
                    res.push_back({S[""], i});
        }

为什么只算一边啊,左右两边不是都可以为空字符吗


用户头像
SoupHu   2022-12-06 23:01         踩      回复

这个答案tle了呀


App 内打开
你确定删除吗?
1024
x

© 2018-2025 AcWing 版权所有  |  京ICP备2021015969号-2
用户协议  |  隐私政策  |  常见问题  |  联系我们
AcWing
请输入登录信息
更多登录方式: 微信图标 qq图标 qq图标
请输入绑定的邮箱地址
请输入注册信息