问题
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.
Example 1:
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:
Input:
words = ["bat","tab","cat"]
Output:
[[0,1],[1,0]]
Explanation:
The palindromes are ["battab","tabbat"]
Example 3:
Input:
words = ["a",""]
Output:
[[0,1],[1,0]]
Constraints:
1 <= words.length <= 50000 <= words[i].length <= 300words[i]consists of lower-case English letters.
解答
Trie:
时间复杂度O(nk^2)
- 构造:Trie树的构造单词反序存放,并增加一个单词结束标识。
- 匹配:
- 当要查找单词A比当前Trie分支上的单词B长:前面匹配均成功,需要判断要找到单词A多出部分是不是回文。
- 当要查找单词A比当前Trie分支上的单词B短:前面匹配均成功,需要判断该分支上的单词剩余部分是不是回文。
[“acbe”, “ca”, “bca”, “bbac”].
from https://fizzbuzzed.com/top-interview-questions-5/
class Solution:
def getPalindromesForWord(self, trie, word, index):
output = []
while word:
if trie.wordEndIndex >= 0:
if isPalindrome(word):
output.append(trie.wordEndIndex)
if not word[0] in trie.paths:
return output
trie = trie.paths[word[0]]
word = word[1:]
if trie.wordEndIndex >=0:
output.append(trie.wordEndIndex)
output.extend(trie.palindromesBelow)
return output
def palindromePairs(self, words: List[str]) -> List[List[int]]:
trie = makeTrie(words)
output=[]
for i, word in enumerate(words):
candidates = self.getPalindromesForWord(trie, word, i)
output.extend([[i,c] for c in candidates if i!= c])
return output
def isPalindrome(word):
if len(word) == 0 or len (word) == 1:
return True
return word[0] == word[-1] and isPalindrome(word[1:-1])
class Trie:
def __init__(self):
self.paths = defaultdict(Trie)
self.wordEndIndex = -1
self.palindromesBelow = []
def addWord(self, word, index):
trie = self
for j , char in enumerate(reversed(word)):
if isPalindrome(word[0:len(word)-j]):
trie.palindromesBelow.append(index)
trie = trie.paths[char]
trie.wordEndIndex = index
def makeTrie(words):
trie = Trie()
for i, word in enumerate(words):
trie.addWord(word, i)
return trie
穷举:
直接两层循环即可O(n^2k)
def isPalindrome(word):
for i in range(len(word)//2):
if word[i] != word[-1-i]:
return False
return True
def isPalindrome2(word):
if len(word) == 0 or len(word) == 1:
return True
return word[0] == word[-1] and isPalindrome2(word[1:-1])
def isPalindrome3(word):
return word == word[::-1]
def palidromePairs(words):
output = []
for i, firstword in enumerate(words):
for j, secondword in enumerate(words):
if (i == j):
continue
if isPalindrome3(firstword + secondword):
output.append([i, j])
return output
hash表:
思路和Trie是一致的只是单词是逆序存放到到hash表中, 分为两种情况:
- 当前单词比要拼接的单词长
- 当前单词比要拼接的单词短或者相等。
def palidromePairs(words):
output = []
word_to_index = {word: i for i, word in enumerate(words)}
for i, firstword in enumerate(words):
for j in range(len(firstword)+1):
x_reversed = firstword[j:][::-1]
rest = firstword[0:j]
if isPalindrome(rest) and x_reversed in word_to_index and word_to_index[x_reversed] != i:
output.append([word_to_index[x_reversed], i])
if j == len(firstword): continue
x_reversed = firstword[:j][::-1]
rest = firstword[j:]
if isPalindrome(rest) and x_reversed in word_to_index and word_to_index[x_reversed] != i:
output.append([i, word_to_index[x_reversed]])
return output
参考及引用
https://fizzbuzzed.com/top-interview-questions-5/
Photo by Josh Sorenson from Pexels


Comments are closed.