题目描述
题目描述:
给定一组 互不相同 的单词, 找出所有不同 的索引对(i, j),使得列表中的两个单词, words[i] + words[j] ,可拼接成回文串。
示例 1:
输入:["abcd","dcba","lls","s","sssll"]
输出:[[0,1],[1,0],[3,2],[2,4]]
解释:可拼接成的回文串为 ["dcbaabcd","abcddcba","slls","llssssll"]
示例 2:
输入:["bat","tab","cat"]
输出:[[0,1],[1,0]]
解释:可拼接成的回文串为 ["battab","tabbat"]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-pairs
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
暴力破解-枚举前缀和后缀
首先,我们假设有两个串s1和s2,s1+s2合并后是回文串,那么s1和s2会符合这样的情况:
- s1.length() == s2.length(): s1一定是s2的反转。如s1=“abc” ,s2 = “cba”,s1+s2=“abccba”回文,假如不反转就不会回文。
- s1.length() > s2.length(): 那么s1拆成左右两部分t1和t2,t1是s2的反转,而t2是回文串。如s1=“abcc”,s2=“ba”,s1+s2=“abccba”回文,s1拆分为t1=“ab”,t2=“cc”,那么t1=“ab”是s2=“ba”的反转,而t2=“cc”是回文串。
- s1.length() < s2.length(): 这种情况就相当于上面情况2的倒转,这里不做重复描述了。
因此这样,对于每一个字符串,我们令其为 s1 和 s2中较长的那一个,然后找到可能和它构成回文串的字符串即可。
换句话说,就是枚举s1和s2,令其中最长的那个,拆分成两个部分,t1和t2:
- 假如t1是回文串,符合情况3,我们只需要查询给定的字符串序列中是否包含 t2 的翻转
- 假如t2是回文串。符合情况2,我们只需要查询给定的字符串序列中是否包含 t1 的翻转
也就是说,我们要枚举字符串 k 的每一个前缀和后缀,判断其是否为回文串。如果是回文串,我们就查询其剩余部分的翻转是否在给定的字符串序列中出现即可。
因此,我们可以使用哈希表存储所有字符串的翻转串。在进行查询时,我们判断带查询串的子串是否在哈希表中出现,就等价于判断了其翻转是否存在。
代码
//code
class Solution {
//用于记录反转后的字符串
List<String> wordsRev = new ArrayList<String>();
//使用hash表,用于记录反转字符串以及对应的下标
Map<String, Integer> indices = new HashMap<String, Integer>();
public List<List<Integer>> palindromePairs(String[] words) {
int n = words.length;
//字符串反转,加入链表
for (String word: words) {
wordsRev.add(new StringBuffer(word).reverse().toString());
}
//把链表中的反转字符串用hash表记录
for (int i = 0; i < n; ++i) {
indices.put(wordsRev.get(i), i);
}
//定义结果集
List<List<Integer>> ret = new ArrayList<List<Integer>>();
for (int i = 0; i < n; i++) {
String word = words[i];
int m = words[i].length();
if (m == 0) { //空串也是回文,所以跳过
continue;
}
for (int j = 0; j <= m; j++) {
if (isPalindrome(word, j, m - 1)) {
int leftId = findWord(word, 0, j - 1);
if (leftId != -1 && leftId != i) {
ret.add(Arrays.asList(i, leftId));
}
}
if (j != 0 && isPalindrome(word, 0, j - 1)) {
int rightId = findWord(word, j, m - 1);
if (rightId != -1 && rightId != i) {
ret.add(Arrays.asList(rightId, i));
}
}
}
}
return ret;
}
//判断字符串下标为left到right部分是否回文
public boolean isPalindrome(String s, int left, int right) {
int len = right - left + 1;
for (int i = 0; i < len / 2; i++) {
if (s.charAt(left + i) != s.charAt(right - i)) {
return false;
}
}
return true;
}
//获取hash表中反转单词对应的下标,假如不存在该单词就返回-1
public int findWord(String s, int left, int right) {
return indices.getOrDefault(s.substring(left, right + 1), -1);
}
}
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/palindrome-pairs/solution/hui-wen-dui-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。