Given a list of unique words, return all the pairs of the distinct indices (i, j) in the given list, so that the concatenation of the two words words[i] + words[j] is a palindrome.
Input: words =["abcd","dcba","lls","s","sssll"]Output: [[0,1],[1,0],[3,2],[2,4]]Explanation: The palindromes are ["dcbaabcd","abcddcba","slls","llssssll"]
Example 2:
1
2
3
Input: words =["bat","tab","cat"]Output: [[0,1],[1,0]]Explanation: The palindromes are ["battab","tabbat"]
There exists an O(n^2 * k) naive approach for this problem, where n is the total number of words in the words array, and k is the average word length. For each word, we iterate through the words array and check if the concatenation results in a palindrome.
This approach causes a Time Limit Exceeded (TLE) error.
Perform a nested loop on the words array to evaluate pairs of words for palindrome pairs.
Note we dont have to concatenate the strings to check it, we can be smart about it. Rather than concatenating the strings to check for palindromes, the method isPalindrome checks the characters directly from both strings. This approach avoids the overhead of creating new strings.
classTrieNode:
def __init__(self):
self.children = {}
self.index =-1 self.palindromes = []
classSolution:
defis_palindrome(self, word: str, left: int, right: int) -> bool:
while left < right:
if word[left] != word[right]:
returnFalse left +=1 right -=1returnTruedefadd_word(self, root: TrieNode, word: str, index: int) ->None:
for i in range(len(word) -1, -1, -1):
if self.is_palindrome(word, 0, i):
root.palindromes.append(index)
if word[i] notin root.children:
root.children[word[i]] = TrieNode()
root = root.children[word[i]]
root.palindromes.append(index)
root.index = index
defsearch_words(self, words: List[str], i: int, root: TrieNode, ans: List[List[int]]) ->None:
for j in range(len(words[i])):
if root.index >=0and root.index != i and self.is_palindrome(words[i], j, len(words[i]) -1):
ans.append([i, root.index])
if words[i][j] notin root.children:
return root = root.children[words[i][j]]
for j in root.palindromes:
if i != j:
ans.append([i, j])
defpalindromePairs(self, words: List[str]) -> List[List[int]]:
root = TrieNode()
for i, word in enumerate(words):
self.add_word(root, word, i)
ans: List[List[int]] = []
for i in range(len(words)):
self.search_words(words, i, root, ans)
return ans