336. Palindrome Pairs 回文对
給定一組唯一的單詞, 找出所有不同 的索引對(i, j),使得列表中的兩個單詞, words[i] + words[j] ,可拼接成回文串。
示例 1:
輸入: [“abcd”,“dcba”,“lls”,“s”,“sssll”]
輸出: [[0,1],[1,0],[3,2],[2,4]]
解釋: 可拼接成的回文串為 [“dcbaabcd”,“abcddcba”,“slls”,“llssssll”]
示例 2:
輸入: [“bat”,“tab”,“cat”]
輸出: [[0,1],[1,0]]
解釋: 可拼接成的回文串為 [“battab”,“tabbat”]
暴力枚舉
本題可以想到暴力做法,我們枚舉每一對字符串的組合,暴力判斷它們是否能夠構成回文串即可。時間復雜度 O(n2×m),其中 n 是字符串的數量,m 是字符串的平均長度。時間復雜度并不理想,考慮進行優化。
Code
def palindromePairs(self, words: List[str]) -> List[List[int]]:ans = []for i in range(len(words)):for j in range(len(words)):if i != j:temp = words[i] + words[j]if temp == temp[::-1]:ans.append([i, j])return ans字典樹/哈希表+前后綴
假設存在兩個字符串 s1 和 s2,s1+s2 是一個回文串,記這兩個字符串的長度分別為 len1 和 len2,我們分三種情況進行討論:
這樣,對于每一個字符串,我們令其為 s1 和 s2 中較長的那一個,然后找到可能和它構成回文串的字符串即可。
具體地說,我們枚舉每一個字符串 kkk,令其為 s1s_1s1? 和 s2s_2s2? 中較長的那一個,那么 kkk 可以被拆分為兩部分,t1t_1t1? 和 t2t_2t2?。
也就是說,我們要枚舉字符串 kkk 的每一個前綴和后綴,判斷其是否為回文串。如果是回文串,我們就查詢其剩余部分的翻轉是否在給定的字符串序列中出現即可。
注意到空串也是回文串,所以我們可以將 kkk 拆解為 k+?k+\varnothingk+? 或 ?+k\varnothing+k?+k,這樣我們就能將情況 111 也解釋為特殊的情況 222 或情況 333。
而要實現這些操作,我們只需要設計一個能夠在一系列字符串中查詢「某個字符串的子串的翻轉」是否存在的數據結構,有兩種實現方法:
-
我們可以使用字典樹存儲所有的字符串。在進行查詢時,我們將待查詢串的子串逆序地在字典樹上進行遍歷,即可判斷其是否存在。
-
我們可以使用哈希表存儲所有字符串的翻轉串。在進行查詢時,我們判斷帶查詢串的子串是否在哈希表中出現,就等價于判斷了其翻轉是否存在。
字典樹 Code
class Node:def __init__(self):self.ch = [0] * 26self.flag = -1class Solution:def palindromePairs(self, words: List[str]) -> List[List[int]]:tree = [Node()]def insert(s: str, index: int):length = len(s)add = 0for i in range(length):x = ord(s[i]) - ord("a")if tree[add].ch[x] == 0:tree.append(Node())tree[add].ch[x] = len(tree) - 1add = tree[add].ch[x]tree[add].flag = indexdef findWord(s: str, left: int, right: int) -> int:add = 0for i in range(right, left - 1, -1):x = ord(s[i]) - ord("a")if tree[add].ch[x] == 0:return -1add = tree[add].ch[x]return tree[add].flagdef isPalindrome(s: str, left: int, right: int) -> bool:length = right - left + 1return length < 0 or all(s[left + i] == s[right - i] for i in range(length // 2))n = len(words)for i, word in enumerate(words):insert(word, i)ret = list()for i, word in enumerate(words):m = len(word)for j in range(m + 1):if isPalindrome(word, j, m - 1):leftId = findWord(word, 0, j - 1)if leftId != -1 and leftId != i:ret.append([i, leftId])if j and isPalindrome(word, 0, j - 1):rightId = findWord(word, j, m - 1)if rightId != -1 and rightId != i:ret.append([rightId, i])return ret哈希表 Code
def palindromePairs(self, words: List[str]) -> List[List[int]]:def findWord(s: str, left: int, right: int) -> int:return indices.get(s[left: right + 1], -1)def isPalindrome(s: str, left: int, right: int) -> bool:sub = s[left: right + 1]return sub == sub[::-1]n, ret = len(words), list()indices = {word[::-1]: i for i, word in enumerate(words)}for i, word in enumerate(words):m = len(word)for j in range(m + 1):if isPalindrome(word, j, m - 1):leftId = findWord(word, 0, j - 1)if leftId != -1 and leftId != i:ret.append([i, leftId])if j and isPalindrome(word, 0, j - 1):rightId = findWord(word, j, m - 1)if rightId != -1 and rightId != i:ret.append([rightId, i])return ret 與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的336. Palindrome Pairs 回文对的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SpaceX完成“星舰”空中悬停,距载人
- 下一篇: 100. Same Tree 相同的树