leetcode 336. Palindrome Pairs

本文探讨了如何解决回文串配对问题,通过遍历和优化的方式寻找字符串数组中可以形成回文串的配对,并介绍了使用哈希表进行优化的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一开始的思路就是遍历所有的pair,判断这个pair拼接起来是不是回文串,首先,还是拿例子说明

["abcd", "dcba", "lls", "s", "sssll"] 答案:[[0, 1], [1, 0], [3, 2], [2, 4]]。当我遍历到i=2,j=4的时候,即words[i] = "lls",words[j] = "sssll",由于words[i] = "lls"的长度是小于words[j] = "sssll",所以要将”sssll“拆分成两部分,有一部分必须是”lls“的反转串,剩下的那一部分必须是回文串,这样的话words[j] = "sssll"才能拼到words[i] = "lls"的右边,这种情况是len(words[i]) <= len(words[j]);另外一种情况是len(words[i]) > len(words[j]),比如当遍历到i=4,j=2的时候,即words[i] = "sssll",words[j] = "lls",此时words[i] = "sssll"的长度是大于words[j] = "lls",处理的方法与前一种情况类似。实现代码如下:

class Solution {
public:
    vector<vector<int>> palindromePairs(vector<string>& words) {
        vector<vector<int>> resultVec;
        for (int i = 0; i < words.size(); i++) {
            for (int j = 0; j < words.size(); j++) {
                if (i == j) {
                    continue;
                }
                bool palidromeFlag = true, reverseFlag = true;
                if (words[i].size() <= words[j].size()) {
                    palidromeFlag = isPalidrome(words[j].substr(0, int(words[j].size()) - int(words[i].size())));
                    reverseFlag = isReverse(words[i], words[j].substr(int(words[j].size()) - int(words[i].size()), int(words[i].size())));
                } else {
                    palidromeFlag = isPalidrome(words[i].substr(int(words[j].size()), int(words[i].size()) - int(words[j].size())));
                    reverseFlag = isReverse(words[i].substr(0, int(words[j].size())), words[j]);
                }
                if (palidromeFlag && reverseFlag) {
                    vector<int> singleResult = {i, j};
                    resultVec.push_back(singleResult);
                }
            }
        }
        return resultVec;
    }
private:
    bool isPalidrome(string str) {
        int midInd = int(str.size() - 1) / 2;
        int leftInd = int(str.size()) % 2 == 0?midInd:midInd-1;
        int rightInd = midInd + 1;
        while (leftInd >= 0 && rightInd < str.size()) {
            if (str[leftInd] != str[rightInd]) {
                return false;
            }
            leftInd--;
            rightInd++;
        }
        return true;
    }
    bool isReverse(string leftStr, string rightStr) {
        int strSize = int(leftStr.size());
        for (int i = 0; i < strSize; i++) {
            if (leftStr[i] != rightStr[strSize - 1 - i]) {
                return false;
            }
        }
        return true;
    }
};

但是提交上去遇到这个case的时候TLE了。改进思路,每次遍历的时候都要算一次isReverse,如果用一个哈希表存放candidates的反转字符串,比对的时候直接访问哈希表就可以了,用空间换时间。而且这样的话就不需要O(N^2)的遍历,只需要O(N)遍历的基础上遍历所有可能反转字符串。要注意空字符串的问题

class Solution {
public:
    vector<vector<int>> palindromePairs(vector<string>& words) {
        unordered_map<string, int> hashTable;
        for (int i = 0; i < words.size(); i++) {
            string reverseStr = words[i];
            reverse(reverseStr.begin(), reverseStr.end());
            hashTable[reverseStr] = i;
        }
        vector<vector<int>> resultVec;
        for (int i = 0; i < words.size(); i++) {
            if (words[i].size() == 0) {
                for (int j = 0; j < words.size(); j++) {
                    if (j != i && isPalidrome(words[j])) {
                        resultVec.push_back({i, j});
                    }
                }
            }
            for (int j = 0; j < words[i].size(); j++) {
                string leftStr = words[i].substr(0, j), rightStr = words[i].substr(j, words[i].size() - j);
                //分为在左拼接,在右拼接,这样就不用O(N^2)遍历
                //在右拼接,还要考虑到candidate本身就是回文串的情况,加多一个判断条件
                if (isPalidrome(rightStr) && hashTable.find(leftStr) != hashTable.end() && hashTable[leftStr] != i) {
                    resultVec.push_back({i, hashTable[leftStr]});
                }
                //在左拼接
                if (isPalidrome(leftStr) && hashTable.find(rightStr) != hashTable.end() && hashTable[rightStr] != i) {
                    resultVec.push_back({hashTable[rightStr], i});
                }
            }
        }
        return resultVec;
    }
private:
    bool isPalidrome(string str) {
        int midInd = int(str.size() - 1) / 2;
        int leftInd = int(str.size()) % 2 == 0?midInd:midInd-1;
        int rightInd = midInd + 1;
        while (leftInd >= 0 && rightInd < str.size()) {
            if (str[leftInd] != str[rightInd]) {
                return false;
            }
            leftInd--;
            rightInd++;
        }
        return true;
    }
};
据说还有就TRIE的做法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值