一开始的思路就是遍历所有的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的做法。