leetcode No336. Palindrome Pairs
Posted Dufre.WC
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode No336. Palindrome Pairs相关的知识,希望对你有一定的参考价值。
Question
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:
Input: ["abcd","dcba","lls","s","sssll"]
Output: [[0,1],[1,0],[3,2],[2,4]]
Explanation: The palindromes are ["dcbaabcd","abcddcba","slls","llssssll"]
Example 2:
Input: ["bat","tab","cat"]
Output: [[0,1],[1,0]]
Explanation: The palindromes are ["battab","tabbat"]
Algorithm
暴力法我就不说了,暴力法时间复杂度为O(n×n×k),k为单词的平均长度。
下面来具体分析,先来看字符串s1(长度为k1),字符串s2(长度为k2)组合在一起判断是否是一个回文串有哪几种情况?
- k1 = k2
- k1 < k2
s2剩下的部分必须要满足回文 - k1 > k2
s1剩下的部分必须要满足回文
思考两个问题?
- 假设s1的首字符是a,怎么快速找到以a结尾的字符串?
- 构建Trie,只不过要反着构建
- 第2,3种情况,如何快速的知道剩下的部分是否是回文?
- 第2种情况,已知s1,查找s2,s1先遍历完,因此在遍历到s2的节点b时,为了能快速判断剩下的部分是回文,只要记录从该节点向后所有剩余能构成回文的字符串的下标即可。
- 第3种情况,已知s1,查找s2,s2先遍历完,只需要判断s1剩下的部分是回文即可。
因此,需要构建的前缀树的结构如下:
class TrieNode
public TrieNode[] children;
public int index; //题目要求返回下标,因为这里记录下标
public List<Integer> suffixs; //记录节点向后所有的剩余能构成回文的字符串下标
public TrieNode()
this.children = new TrieNode[26];
this.index = -1;
this.suffixs = new ArrayList<>();
一个简单示例:
- 构建图示
- 查找图示(以字符串"a"为例)
完整代码如下: - 构建
- 字符串取反;
- 遍历word,创建节点;
word.substring(j+1)
为回文,则添加到该节点的suffixs列表中;这里要注意word本身为回文则添加到root节点的suffixs列表中;
- 查找
- 遍历word;
- 如果
word.substring(j)
为回文,则要看当前节点是否为一个单词,如果是,添加到结果中;(对应第三种情况,k1 > k2) - word遍历结束且有以word结尾的单词,则要看当前节点的suffixs列表;(对应第二种情况,k1 < k2)
Code
class Solution
private TrieNode root;
public boolean isPalindrome(String s)
int i=0, j=s.length()-1;
while (i < j)
if (s.charAt(i) != s.charAt(j))
return false;
i++;
j--;
return true;
public List<List<Integer>> palindromePairs(String[] words)
this.root = new TrieNode();
int n = words.length;
//build TrieNode Tree
for (int i=0; i<n; i++)
String word = new StringBuilder(words[i]).reverse().toString();
TrieNode cur = root;
if (isPalindrome(word.substring(0)))
cur.suffixs.add(i);
for (int j=0; j<word.length(); j++)
int index = word.charAt(j) - 'a';
if (cur.children[index] == null)
cur.children[index] = new TrieNode();
cur = cur.children[index];
if (isPalindrome(word.substring(j+1)))
cur.suffixs.add(i);
cur.index = i;
//search
List<List<Integer>> res = new ArrayList<>();
for (int i=0; i<n; i++)
String word = words[i];
TrieNode cur = root;
int j=0;
for (; j<word.length(); j++)
if (isPalindrome(word.substring(j)) && cur.index!=-1)
res.add(Arrays.asList(i, cur.index));
int index = word.charAt(j) - 'a';
if (cur.children[index] == null)
break;
cur = cur.children[index];
if (j == word.length())
for (int k : cur.suffixs)
if (k != i)
res.add(Arrays.asList(i, k));
return res;
class TrieNode
public TrieNode[] children;
public int index;
public List<Integer> suffixs;
public TrieNode()
this.children = new TrieNode[26];
this.index = -1;
this.suffixs = new ArrayList<>();
时间复杂度:O(n×k×k),因为k在一定范围内,所以这个问题优化为一个线性问题。
更多算法总结请关注我的微信公众号《Coder101》
以上是关于leetcode No336. Palindrome Pairs的主要内容,如果未能解决你的问题,请参考以下文章
leetcode No336. Palindrome Pairs
LeetCode 336. Palindrome Pairs(回文对)