题目来源
题目描述
class Solution {
public:
vector<vector<int>> palindromePairs(vector<string>& words) {
}
};
题目解析
分析数据量
如果暴力匹配: 15 ∗ 1 0 5 15 * 10^5 15∗105,可以通过
是否可以哈希桶计数?
分析题意
从words数组中任意选择两个单词,看是否能组成回文串,并返回能组成回文串的索引数组。
注意[0,1]和[1,0]是不一样的
暴力(超时)
穷举 i , j i,j i,j,找出所有的组合可能。如果是回文此,就把对应的 ( i , j ) (i,j) (i,j)推入结果数组。
时间复杂度 O ( ( N 2 ) ∗ L ) O((N^2) * L) O((N2)∗L), N N N是单词个数, L L L是单词平均长度
class Solution {
bool isPalindrome(std::string str){
if(str.empty()){
return true;
}
int i = 0, j = (int)str.size() - 1;
while (i <= j){
if(str[i] != str[j]){
return false;
}
i++;
j--;
}
return true;
}
public:
vector<vector<int>> palindromePairs(vector<string>& words) {
vector<vector<int>> res;
int N = words.size();
for (int i = 0; i < N; ++i) {
for (int j = 0; j < N; ++j) {
if(i != j){
if (isPalindrome(words[i] + words[j])) res.push_back({i, j});
}
}
}
return res;
}
};
class Solution {
public:
vector<vector<int>> palindromePairs(vector<string>& words) {
vector<vector<int>> result{};
int const size = words.size();
for (int i = 0; i < size; ++i)
for (int j = i + 1; j < size; ++j)
{
if (ispalindrome(words[i], words[j]))
result.push_back(vector<int>({i,j}));
if (ispalindrome(words[j], words[i]))
result.push_back(vector<int>({j,i}));
}
return result;
}
private:
bool ispalindrome(string const & word_left, string const & word_right) {
int const sizel = word_left.size();
int const sizer = word_right.size();
int l = 0;
int r = sizel + sizer - 1;
while (l < r) {
char left = (l < sizel) ? (word_left[l]) : (word_right[l - sizel]) ;
char right = (r < sizel) ? (word_left[r]) : (word_right[r - sizel]);
if (left != right) return false;
++l, --r;
}
return true;
}
};
枚举前缀和后缀
- 为了能快速找出翻转词,我们提前将单词都翻转一遍,存入哈希表,还有它对应的索引。
class Solution {
bool isPalindrome(std::string str){
if(str.empty()){
return true;
}
int i = 0, j = (int)str.size() - 1;
while (i <= j){
if(str[i] != str[j]){
return false;
}
i++;
j--;
}
return true;
}
public:
vector<vector<int>> palindromePairs(vector<string>& words) {
int N = words.size();
std::map<std::string, int> reverse_map;
for (int i = 0; i < N; ++i) {
auto word = words[i];
std::reverse(word.begin(), word.end());
reverse_map.insert({word, i});
}
vector<vector<int>> res;
for (int i = 0; i < N; ++i) {
std::string word = words[i];
//当自己是回文,存在""时,可以组成两对
auto it = reverse_map.find("");
if(it != reverse_map.end() && (reverse_map[""] != i) && isPalindrome(word)){
res.emplace_back(vector<int>{reverse_map[""], i});
res.emplace_back(vector<int>{i, reverse_map[""]});
}
// 自己不是回文时,可以与自己的逆序组成一对
if(!isPalindrome(word)){ // abcd ----> dcba ---> abcd
auto tmp = words[i];
if(reverse_map.find(tmp) != reverse_map.end() && reverse_map[tmp] != i){
res.emplace_back(vector<int>{i, reverse_map[tmp]});
}
}
// 枚举前缀和后缀
for (int j = 1; j <= word.size() - 1; ++j) {// 拆分
auto left = word.substr(0, j); // 左边部分
auto right = word.substr(j); // 右边部分
//fb + [aa]bf
if(isPalindrome(left) && reverse_map.find(right) != reverse_map.end() && reverse_map[right] != i){
res.emplace_back(vector<int>{reverse_map[right], i}); // 左边是回文,右边能找到翻转且不是自己
}
// af[cc] + fa
if(isPalindrome(right) && reverse_map.find(left) != reverse_map.end() && reverse_map[left] != i){
res.emplace_back(vector<int>{i, reverse_map[left]}); // 左边是回文,右边能找到翻转且不是自己
}
}
}
return res;
}
};