leetcode 336 Palindrome Pairs

lc 336 Palindrome Pairs

最简单的就是每两个都拼接一下,然后判断是否为回文串

时间复杂度为o(n^2*k) n:words个数 k:word平均长度

 

但是我们仔细观察一下,两个word拼接之后,是如何判断是否为回文串的呢?首尾指针,匹配,向中间收缩。

假如现在有一个单词"asad",有可能和它组成回文串的字母一定结尾是a,"???????a",倒数第二个字母一定是s,这样不就减少无效的比对,从而减少时间复杂度了吗?

但是如何实现呢?

这里用到trie的思想

root为空

子节点为a~z

迭代向下

每一个叶子节点向上到达root节点的路径,一定能构成原数组中的一个word

举例说明

数组:["asad", "ascc", "azlp"]

root

a 

s      z

a  c    l

d  c    p

这样一个数据结构可以满足我们上述思路的要求

只需要遍历一次原数组,依次检查words[i],找出能和它组成回文串的word

 

实现时,注意要从words尾部开始构建trie树,上面的例子是从头开始的,反了

能组成回文串有三种情况

word A & word B

1.A和B等长

那么只需要一直从root往下走(一个for循环,i=0,i<A.length())走A步,都能匹配上,说明AB能组成回文串

举例来说,

原数组为:["asad", "dasa"]tire树为

a  d

s  a

a  s

d  a

我们首先检查words[0] : "asad"

root->a节点 找到

->s节点 找到

->a节点 找到

->d节点 找到

匹配成功 0,1可以组成回文串

 

2.A>B

A:"asadgg"

B:"dasa

"asad"匹配完毕,但是匹配到g时,后面没有节点了

这个时候,就需要检查A在"asad"之后的子串是否为回文串

若是,则asad + 子串 + dasa肯定能构成回文串

 

3.A<B

A:"asad"

B:"dasagg"

"asad"匹配完毕,但是到d就截止了,因为我们的for循环是以A的长度为止的

那么就需要检查B串"dasa"之后的子串是否为回文串了

结论同上,不过这里有个小方法,可以在自建trieNode类中加一个isP[]数组,用来记录之后子串为回文串的单词索引,避免了每次都要重新比较

 

 1 class Solution {
 2     private static class trieNode{
 3         trieNode[] next;
 4         int index;
 5         List<Integer> isP;
 6         
 7         trieNode(){
 8             next = new trieNode[26];
 9             index = -1;
10             isP = new ArrayList<Integer>();
11         }
12         
13     }
14     public List<List<Integer>> palindromePairs(String[] words) {
15         List<List<Integer>> res = new ArrayList<>();
16         trieNode root = new trieNode();
17         
18         for(int i=0; i<words.length; i++){
19             addWord(root, words[i], i);
20         }
21         
22         for(int i=0; i<words.length; i++){
23             search(res, root, words[i], i);
24         }
25         return res;
26     }
27     
28     private void addWord(trieNode root, String s, int index){
29         for(int i=s.length()-1; i>=0; i--){
30             int j = s.charAt(i)-'a';
31             if(root.next[j] == null){
32                 root.next[j] = new trieNode();
33             }
34             if(laterIsP(s, 0, i)){
35                 root.isP.add(index);
36             }
37             
38             root = root.next[j];
39             
40         }
41         root.isP.add(index);
42         root.index = index;
43     }
44     
45     private boolean laterIsP(String s, int i, int j){
46         while(i < j){
47             if(s.charAt(i++) != s.charAt(j--))
48                 return false;
49         }
50         
51         return true;
52     }
53     
54     private void search(List<List<Integer>> res, trieNode root, String s, int index){
55         for(int i=0; i<s.length(); i++){
56             if(root.index >= 0 && index != root.index && laterIsP(s, i, s.length()-1)){
57                 res.add(Arrays.asList(index, root.index)); 
58             }
59             root = root.next[s.charAt(i)-'a'];
60             if(root == null)
61                 return;
62                 
63         }
64         
65         for(int i : root.isP){
66             if(i != index)
67                 res.add(Arrays.asList(index, i));
68         }
69     }
70 }

 

posted @ 2019-06-21 10:33  南山南北秋悲  阅读(213)  评论(0编辑  收藏  举报