LeetCode-Palindrome Pairs

LiBlog發表於2016-08-22

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"]

Credits:
Special thanks to @dietpepsi for adding this problem and creating all test cases.

Analysis:

We use Trie to build a suffix tree to reduce searching range, i.e., for a word starting with 'a', we only search words ending with 'a'.

To find the pairs for each word, we need address two cases:

1. word A is word B's suffix, e.g., "cd" + "babdc". In this case, we should record that "babdc" is a palindrome, if we exclude its suffix of "dc". So we can create a list of words at any TrieNode. This list contains all words that are palindrome if excluding the suffix presented by that TrieNode.

2. word B is word A's suffix, e.g. "dcbab" + "cd". In this case, when search for "dcbab", we should check for every prefix that is also a word, e.g., "dc" of "dcbab" is the word "cd", if excluding this prefix, word A is a palindrome.

Solution:

 1 public class Solution {
 2     public class TrieNode {
 3         TrieNode[] childs;
 4         int wordInd; // index of the word ending at this
 5         List<Integer> pList; // index list of the words which are palindrome if
 6                                 // excluding the prefix on this.
 7 
 8         public TrieNode() {
 9             childs = new TrieNode[26];
10             wordInd = -1;
11             pList = new ArrayList<Integer>();
12         }
13     }
14 
15     public List<List<Integer>> palindromePairs(String[] words) {
16         TrieNode root = new TrieNode();
17 
18         // Build the Trie
19         for (int i = 0; i < words.length; i++) {
20             addWord(words, i, root);
21         }
22 
23         // Build result list
24         List<List<Integer>> resList = new ArrayList<List<Integer>>();
25         for (int i = 0; i < words.length; i++) {
26             findPalindrome(words, i, root, resList);
27         }
28         return resList;
29     }
30 
31     // Add word into Trie.
32     public void addWord(String[] words, int cur, TrieNode root) {
33         TrieNode curNode = root;
34         String word = words[cur];
35         for (int i = word.length() - 1; i >= 0; i--) {
36             // if word(0,i) is a palindrome, i.e., after excluding current
37             // suffix, add it into pList.
38             if (isPalindrome(word, 0, i)) {
39                 curNode.pList.add(cur);
40             }
41 
42             // Move to next char.
43             char curChar = word.charAt(i);
44             if (curNode.childs[curChar - 'a'] == null) {
45                 curNode.childs[curChar - 'a'] = new TrieNode();
46             }
47             curNode = curNode.childs[curChar - 'a'];
48         }
49         // Record the current word's index at the last TrieNode.
50         curNode.wordInd = cur;
51     }
52 
53     // find palindrome for words[cur].
54     public void findPalindrome(String[] words, int cur, TrieNode root, List<List<Integer>> resList) {
55         TrieNode curNode = root;
56         String word = words[cur];
57         for (int i = 0; i < word.length(); i++) {
58             // If there is a word ending at current node, check whether that
59             // word and current word are palindrome pair.
60             if (curNode.wordInd != -1 && isPalindrome(word, i, word.length() - 1)) {
61                 resList.add(Arrays.asList(cur, curNode.wordInd));
62             }
63 
64             // Move to next node; if no next node then return.
65             char curChar = word.charAt(i);
66             if (curNode.childs[curChar - 'a'] == null)
67                 return;
68             curNode = curNode.childs[curChar - 'a'];
69         }
70         // For the last TrieNode, its word should not be current word.
71         if (curNode.wordInd!=-1 && curNode.wordInd!=cur){
72             resList.add(Arrays.asList(cur,curNode.wordInd));
73         }
74 
75         // After reaching the end, further check whether there are words that
76         // are palindrome if current word is a suffix.
77         for (int ind : curNode.pList) {
78             resList.add(Arrays.asList(cur, ind));
79         }
80     }
81 
82     // Returns if word is a palindrome between index i and j.
83     public boolean isPalindrome(String word, int i, int j) {
84         while (i < j) {
85             if (word.charAt(i) == word.charAt(j)) {
86                 i++;
87                 j--;
88             } else
89                 return false;
90         }
91         return true;
92     }
93 }

 

相關文章