(i, j)
in the given list, so that the concatenation of the two words, i.e.
words[i] + words[j]
is a palindrome.
Example 1:
Given words
= ["bat", "tab", "cat"]
Return [[0, 1], [1, 0]]
The palindromes are ["battab", "tabbat"]
Example 2:
Given words
= ["abcd", "dcba", "lls", "s", "sssll"]
Return [[0, 1], [1, 0], [3, 2], [2, 4]]
The palindromes are ["dcbaabcd", "abcddcba", "slls", "llssssll"]
Steps:
-
Traverse the array, build map. Key is the reversed string, value is index in array (0 based)
-
Edge case - check if empty string exists. It’s interesting that for given words {“a”, “”}, it’s expected to return two results [0,1] and [1,0]. Since my main logic can cover [0, 1] concatenate(“a”, “”), so as to cover the other situation concatenate(“”, “a”), I need to traverse the words array again, find the palindrome word candidate except “” itself, and add pair(“”, palindrome word) to the final answer.
-
Main logic part. Partition the word into left and right, and see 1) if there exists a candidate in map equals the left side of current word, and right side of current word is palindrome, so concatenate(current word, candidate) forms a pair: left | right | candidate. 2) same for checking the right side of current word: candidate | left | right.
-
时间复杂度为: O(n * k^2), 其中n为单词的数量,k为单词的位数。
-
class Solution { public: vector<vector<int>> palindromePairs(vector<string>& words) { vector<vector<int>> ret; unordered_map<string, int> dict; for (int i = 0; i < words.size(); ++i) { string s = words[i]; reverse(s.begin(), s.end()); dict[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, words[i].size() - j); if (dict.find(left) != dict.end() && IsPalindrome(right) && dict[left] != i) { ret.push_back({i, dict[left]}); if (left.empty()) { ret.push_back({dict[left], i}); } } if (dict.find(right) != dict.end() && IsPalindrome(left) && dict[right] != i) { ret.push_back({dict[right], i}); } } } return ret; } bool IsPalindrome(const string &s) { for (int left = 0, right = s.size() - 1; left < right; ++left, --right) { if (s[left] != s[right]) return false; } return true; } };