给定一组唯一的单词, 找出所有不同 的索引对(i, j),使得列表中的两个单词, words[i] + words[j] ,可拼接成回文串。
示例 1:
输入: [“abcd”,“dcba”,“lls”,“s”,“sssll”]
输出: [[0,1],[1,0],[3,2],[2,4]]
解释: 可拼接成的回文串为 [“dcbaabcd”,“abcddcba”,“slls”,“llssssll”]
暴力解法
class Solution {
public:
bool isPalindrome(const string& word) {
int t_len = word.size();
int bound = t_len / 2;
int k;
for (k = 0; k < bound; k++) {
if (word[k] != word[t_len - k - 1]) {
return false;
}
}
return true;
}
vector<vector<int>> palindromePairs(vector<string>& words) {
int len = words.size();
vector<vector<int>> ans;
vector<int> t;
for (int i = 0; i < len; i++) {
for (int j = i + 1; j < len; j++) {
bool flag = false;
if (!words[i].size() || !words[j].size()) {
flag = true;
}
// 做一个简单验证 减少字符串拼接的消耗
if ( flag || words[i][0] == words[j][words[j].size() - 1]) {
string temp = words[i] + words[j];
if (isPalindrome(temp)) {
t.clear();
t.push_back(i);
t.push_back(j);
ans.push_back(t);
}
}
if ( flag || words[j][0] == words[i][words[i].size() - 1]) {
string temp = words[j] + words[i];
if (isPalindrome(temp)) {
t.clear();
t.push_back(j);
t.push_back(i);
ans.push_back(t);
}
}
}
}
return ans;
}
};
解法2 (来自 https://www.jianshu.com/p/544f75c359e8)
class Solution {
public:
vector<vector<int>> palindromePairs(vector<string>& words) {
vector<vector<int>> res;
unordered_map<string, int> m; // m里放了字符串和字符串在words中的索引
set<int> s; // s里放了所有字符串的长度
for (int i = 0; i < words.size(); ++i) {
m[words[i]] = i;
s.insert(words[i].size());
}
for (int i = 0; i < words.size(); ++i) {
string t = words[i];
int len = t.size();
// 找逆序的字符串
reverse(t.begin(), t.end());
if (m.count(t) && m[t] != i) {
// 可以直接这样push
// m[t]也会这样重复一次 所以不需要push两次
res.push_back({i, m[t]});
}
// 如果某个字符串能找到一个分割点,分割点前的部分是回文,后半部分翻转后也在数组里,可组成一对。如果后部分是回文,前半部分翻转后在数组里,可组成一对。
auto a = s.find(len);
// 只在长度比s小的找 set是有序集合
for (auto it = s.begin(); it != a; ++it) {
int d = *it;
if (isValid(t, 0, len - d - 1) && m.count(t.substr(len - d))) {
res.push_back({i, m[t.substr(len - d)]});
}
if (isValid(t, d, len - 1) && m.count(t.substr(0, d))) {
res.push_back({m[t.substr(0, d)], i});
}
}
}
return res;
}
bool isValid(string t, int left, int right) {
while (left < right) {
if (t[left++] != t[right--]) return false;
}
return true;
}
};
C++使用总结
- set map有序 (用树) unordered_set unordered_map无序 (用hash)
- vector初始化
vector<vector<int>> v; v.push_back({1,2}); // 可以
- v1v2都是vector v1.push_back(v2)发生了什么?
push_back会对传递进来的参数进行一次拷贝(调用拷贝构造函数) 当vector调用拷贝构造函数时,容器里面的对象都会被拷贝一份(浅拷贝)到新的容器里 reverse(t.begin(), t.end());
前闭后开string substr (size_t pos = 0, size_t len = npos) const;