LeetCode 336. Palindrome Pairs(回文对)
Posted jmspan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 336. Palindrome Pairs(回文对)相关的知识,希望对你有一定的参考价值。
原题网址:https://leetcode.com/problems/palindrome-pairs/
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"]
方法:通过Trie来发现对称的单词。
public class Solution
private boolean palindrome(char[] word, int i, int j)
while (i<j) if (word[i++] != word[j--]) return false;
return true;
public List<List<Integer>> palindromePairs(String[] words)
List<List<Integer>> pairs = new ArrayList<>();
if (words == null || words.length == 0) return pairs;
char[][] was = new char[words.length][];
TrieNode root = new TrieNode();
for(int i=0; i<words.length; i++)
was[i] = words[i].toCharArray();
TrieNode node = root;
for(int j=0; j<was[i].length; j++) node = node.next(was[i][j]);
node.id = i;
if (root.id != -1)
for(int i=0; i<was.length; i++)
if (i != root.id && palindrome(was[i], 0, was[i].length-1))
Integer[] pair = new Integer[2];
pair[0] = root.id;
pair[1] = i;
pairs.add(Arrays.asList(pair));
pair = new Integer[2];
pair[0] = i;
pair[1] = root.id;
pairs.add(Arrays.asList(pair));
for(int i=0; i<was.length; i++)
if (was[i].length == 0) continue;
TrieNode node = root;
for(int j=was[i].length-1; j>=0; j--)
node = node.nexts[was[i][j]-'a'];
if (node == null) break;
// System.out.printf("i=%d, j=%d, words[%d]=%s, node.id=%d, palindrome=%b\\n", i, j, i, words[i], node.id, palindrome(was[i], 0, j-1));
if (node.id == -1 || node.id == i || !palindrome(was[i], 0, j-1)) continue;
Integer[] pair = new Integer[2];
pair[0] = node.id;
pair[1] = i;
pairs.add(Arrays.asList(pair));
if (node != null)
LinkedList<TrieNode> queue = new LinkedList<>();
queue.add(node);
while (!queue.isEmpty())
TrieNode trie = queue.remove();
if (trie.id != -1 && trie.id != i && was[trie.id].length != 0 && was[trie.id].length != was[i].length
&& palindrome(was[trie.id], was[i].length, was[trie.id].length-1))
Integer[] pair = new Integer[2];
pair[0] = trie.id;
pair[1] = i;
pairs.add(Arrays.asList(pair));
for(int j=0; j<trie.size; j++) queue.add(trie.nexts[trie.trans[j]]);
return pairs;
class TrieNode
int id = -1;
TrieNode[] nexts = new TrieNode[26];
char[] trans = new char[26];
int size = 0;
TrieNode next(char ch)
char id = (char)(ch-'a');
if (nexts[id] == null)
trans[size++] = id;
nexts[id] = new TrieNode();
return nexts[id];
另一个实现方式:
public class Solution
public List<List<Integer>> palindromePairs(String[] words)
Trie root = new Trie();
char[][] was = new char[words.length][];
for(int i=0; i<words.length; i++)
was[i] = words[i].toCharArray();
Trie node = root;
for(int j=0; j<was[i].length; j++) node = node.append(was[i][j]);
node.w = i;
List<List<Integer>> results = new ArrayList<>();
if (root.w != -1)
for(int i=0; i<was.length; i++)
if (i==root.w) continue;
int left = 0, right = was[i].length-1;
for(; left < right && was[i][left] == was[i][right]; left ++, right --);
if (left >= right)
Integer[] pair = new Integer[2];
pair[0] = root.w;
pair[1] = i;
// System.out.printf("1 root.w=%d, i=%d, pair=[%d, %d]\\n", root.w, i, pair[0], pair[1]);
results.add(Arrays.asList(pair));
pair = new Integer[2];
pair[0] = i;
pair[1] = root.w;
// System.out.printf("2 root.w=%d, i=%d, pair=[%d, %d]\\n", root.w, i, pair[0], pair[1]);
results.add(Arrays.asList(pair));
for(int i=0; i<was.length; i++)
Trie node = root;
for(int j=was[i].length-1; j>=0; j--)
node = node.nexts[was[i][j]-'a'];
if (node == null) break;
if (node.w != -1 && node.w != i)
int left = 0, right = was[i].length-was[node.w].length-1;
for(; left < right && was[i][left] == was[i][right]; left ++, right --);
if (left >= right)
Integer[] pair = new Integer[2];
pair[0] = node.w;
pair[1] = i;
// System.out.printf("3 node.w=%d, i=%d, pair=[%d, %d]\\n", node.w, i, pair[0], pair[1]);
results.add(Arrays.asList(pair));
if (node != root && node != null)
LinkedList<Trie> queue = new LinkedList<>();
for(int j=0; j<node.size; j++) queue.add(node.nexts[node.letters[j]-'a']);
while (!queue.isEmpty())
Trie q = queue.remove();
if (q.w != -1 && q.w != i)
int left = was[i].length, right = was[q.w].length-1;
for(; left < right && was[q.w][left] == was[q.w][right]; left ++, right --);
if (left >= right)
Integer[] pair = new Integer[2];
pair[0] = q.w;
pair[1] = i;
// System.out.printf("4 q.w=%d, i=%d, pair=[%d, %d]\\n", q.w, i, pair[0], pair[1]);
results.add(Arrays.asList(pair));
for(int j=0; j<q.size; j++) queue.add(q.nexts[q.letters[j]-'a']);
return results;
class Trie
int w = -1;
char[] letters = new char[26];
int size;
Trie[] nexts = new Trie[26];
Trie append(char ch)
if (nexts[ch-'a'] != null) return nexts[ch-'a'];
letters[size++] = ch;
nexts[ch-'a'] = new Trie();
return nexts[ch-'a'];
如果不想使用广度优先,则可以建立前缀树和后缀树,分别检查。
public class Solution
public List<List<Integer>> palindromePairs(String[] words)
List<List<Integer>> results = new ArrayList<>();
Trie forward = new Trie();
Trie reverse = new Trie();
char[][] was = new char[words.length][];
for(int i = 0; i < words.length; i++)
was[i] = words[i].toCharArray();
Trie f = forward;
for(int j = 0; j < was[i].length; j++)
f = f.append(was[i][j]);
f.id = i;
Trie r = reverse;
for(int j = was[i].length - 1; j >= 0; j--)
r = r.append(was[i][j]);
r.id = i;
for(int i = 0; i < words.length; i++)
Trie f = forward;
int j = was[i].length - 1;
for(; j >= 0 && f != null; j--)
if (f.id != -1 && f.id != i)
int left = 0, right = j;
for(; left < right && was[i][left] == was[i][right]; left++, right--);
if (left >= right)
Integer[] result = new Integer[2];
result[0] = f.id;
result[1] = i;
results.add(Arrays.asList(result));
f = f.nexts[was[i][j] - 'a'];
if (j < 0 && f != null && f.id != -1 && f.id < i)
Integer[] result = new Integer[2];
result[0] = f.id;
result[1] = i;
results.add(Arrays.asList(result));
result = new Integer[2];
result[0] = i;
result[1] = f.id;
results.add(Arrays.asList(result));
Trie r = reverse;
j = 0;
for(; j < was[i].length && r != null; j++)
if (r.id != -1 && r.id != i)
int left = j, right = was[i].length - 1;
for(; left < right && was[i][left] == was[i][right]; left++, right--);
if (left >= right)
Integer[] result = new Integer[2];
result[0] = i;
result[1] = r.id;
results.add(Arrays.asList(result));
r = r.nexts[was[i][j] - 'a'];
// 引起重复
// if (j == was[i].length && r != null && r.id != -1 && i != r.id)
// Integer[] result = new Integer[2];
// result[0] = i;
// result[1] = r.id;
// results.add(Arrays.asList(result));
//
return results;
class Trie
int id = -1;
Trie[] nexts = new Trie[26];
Trie append(char ch)
if (nexts[ch - 'a'] == null) nexts[ch - 'a'] = new Trie();
return nexts[ch - 'a'];
注意当两个字符串长度相等、字符顺序相反的时候,如何去除重复。
另一种方法是不使用Trie,而是按照长度穷举切分方法,参考:https://leetcode.com/discuss/93603/150-ms-45-lines-java-solution
以上是关于LeetCode 336. Palindrome Pairs(回文对)的主要内容,如果未能解决你的问题,请参考以下文章
leetcode No336. Palindrome Pairs
leetcode No336. Palindrome Pairs