Given a list of unique words. Find all pairs of distinct indices (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"]
这道题是在字符串中找能够构成回文的字符串对,题目难度为Hard。
将构成回文的两个字符串记为s1和s2,构成回文的形式是s1+s2。如果s1长度比s2小,将s2分为左右两部分ls和rs,其中rs和s1长度相等,则rs倒序后和s1是相同的,同时ls自身也是回文;如果s1长度比s2大,将s1分为左右两部分ls和rs,其中ls和s2长度相等,则ls倒序后和s2是相同的,同时rs自身也是回文;如果s1和s2长度相等,相当于ls或rs为空字符串,则s1倒序后和s2相同。
依照上述分析,我们可以遍历字符串数组,针对每个字符串在任意位置将其分为左右两部分ls和rs(可以为空字符串),然后判断两部分是否是回文,如果ls是回文,相当于将本字符串放置在回文字符串的右边,判断rs倒序后是否在原始字符串中,如果在则构成回文(注意判断是否是同一字符串);同理,如果rs是回文,相当于将本字符串放置在回文字符串的左边,判断ls倒序后是否在原始字符串中,如果在则构成回文(同样需要判断是否是同一字符串)。这里需要注意的是长度相同的两个字符串如果构成回文,两者相对位置可以是s1+s2或者s2+s1,在各自的判断循环中两种情况都会认定为回文,会出现重复的下标对,所以在循环中判断rs回文的同时加了不空的判断,相当于各自减少了一种情况,不影响两者长度不等的情况以及最终结果。具体代码:
class Solution {
bool isPalindrome(string s) {
int l = 0, r = s.size()-1;
while(s[l] == s[r]) {
++l;
--r;
}
return l>r;
}
public:
vector<vector<int>> palindromePairs(vector<string>& words) {
vector<vector<int>> ret;
unordered_map<string, int> hash;
for(int i=0; i<words.size(); ++i) hash[words[i]] = i;
for(int i=0; i<words.size(); ++i) {
for(int j=0; j<=words[i].size(); ++j) {
string ls = words[i].substr(0, j);
string rs = words[i].substr(j);
if(isPalindrome(ls)) {
reverse(rs.begin(), rs.end());
if(hash.find(rs) != hash.end() && hash[rs] != i) {
ret.push_back(vector<int>{hash[rs], i});
}
}
if(!rs.empty() && isPalindrome(rs)) {
reverse(ls.begin(), ls.end());
if(hash.find(ls) != hash.end() && hash[ls] != i) {
ret.push_back(vector<int>{i, hash[ls]});
}
}
}
}
return ret;
}
};