[Swift]LeetCode336. 回文对 | Palindrome Pairs
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/10262002.html
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
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:
Input: ["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: ["bat","tab","cat"]
Output: [[0,1],[1,0]]
Explanation: The palindromes are ["battab","tabbat"]
给定一组唯一的单词, 找出所有不同 的索引对(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"]
1068ms
1 class Solution { 2 class TridNode { 3 var nexts : [Character : TridNode] = [Character : TridNode]() 4 var index : Int = -1 5 var parIndexs = [Int]() 6 } 7 8 func palindromePairs(_ words: [String]) -> [[Int]] { 9 10 var res = [[Int]]() 11 12 let root = TridNode() 13 14 for i in 0..<words.count { 15 buildTrees(root, Array(words[i]), i) 16 } 17 18 for i in 0..<words.count { 19 search(Array(words[i]), i, root, &res) 20 } 21 22 return res 23 } 24 25 func buildTrees(_ root : TridNode, _ wordArr : [Character] , _ index : Int ) { 26 var root = root 27 for i in stride(from: wordArr.count - 1, to: -1, by: -1) { 28 let c = wordArr[i] 29 if root.nexts[c] == nil { 30 root.nexts[c] = TridNode() 31 } 32 if isPalindrome(wordArr, 0, i) { 33 root.parIndexs.append(index) 34 } 35 36 root = root.nexts[c]! 37 } 38 39 root.parIndexs.append(index) 40 root.index = index 41 } 42 43 func search(_ wordArr : [Character], _ i : Int , _ root : TridNode , _ res : inout [[Int]]) { 44 var root = root 45 for j in 0..<wordArr.count { 46 if root.index >= 0 && root.index != i && isPalindrome(wordArr, j, wordArr.count - 1) { 47 res.append([i,root.index]) 48 } 49 50 guard root.nexts[wordArr[j]] != nil else { 51 return 52 } 53 54 root = root.nexts[wordArr[j]]! 55 } 56 57 for j in root.parIndexs where i != j { 58 res.append([i,j]) 59 } 60 61 } 62 63 64 func isPalindrome(_ wordArr : [Character], _ i : Int , _ j : Int) -> Bool { 65 66 var i = i, j = j 67 68 while i < j { 69 if wordArr[i] != wordArr[j] { 70 return false 71 } 72 i += 1 73 j -= 1 74 } 75 76 return true 77 } 78 }
1280ms
1 class Solution { 2 let lowerLetterUnicodeStart = Character("a").char2Int() 3 4 func palindromePairs(_ words: [String]) -> [[Int]] { 5 var result = [[Int]]() 6 let n = words.count 7 let root = TrieNode() 8 9 func addWord(_ root: TrieNode, _ index: Int) { 10 var point = root 11 let word = Array(words[index]) 12 for i in (0..<word.count).reversed() { 13 let char = word[i].char2Int() - lowerLetterUnicodeStart 14 if point.next[char] == nil { point.next[char] = TrieNode() } 15 if isPalindrome(word, 0, i) { point.list.append(index) } 16 if let next = point.next[char] { point = next } 17 } 18 point.list.append(index) 19 point.index = index 20 } 21 22 func search(_ root: TrieNode, _ index: Int) { 23 var point = root 24 let word = Array(words[index]) 25 for i in 0..<word.count { 26 let idx = point.index 27 if idx >= 0, idx != index, isPalindrome(word, i, word.count - 1) { 28 result.append([index, idx]) 29 30 } 31 let char = word[i].char2Int() - lowerLetterUnicodeStart 32 if let next = point.next[char] { point = next } else { return } 33 } 34 for i in point.list where index != i { result.append([index, i]) } 35 } 36 37 for i in 0..<n { addWord(root, i) } 38 for i in 0..<n { search(root, i) } 39 return result 40 } 41 42 func isPalindrome(_ word: [Character], _ i: Int, _ j: Int) -> Bool { 43 var (i, j) = (i, j) 44 while i < j { 45 if word[i] != word[j] { return false } 46 i += 1 47 j -= 1 48 } 49 return true 50 } 51 } 52 53 class TrieNode { 54 var next: [TrieNode?] = Array(repeating: nil, count: 26) 55 var index = -1 56 var list = [Int]() 57 } 58 59 extension Character { 60 func char2Int() -> Int { 61 return Int(self.unicodeScalars.first!.value) 62 } 63 }
1516ms
1 class Solution { 2 func palindromePairs(_ words: [String]) -> [[Int]] { 3 var rslts = [[Int]]() 4 if words.count == 0 { 5 return rslts 6 } 7 8 class Node { 9 var label: Int? 10 var dict: [Character: Node] 11 12 init() { 13 label = nil 14 dict = [:] 15 } 16 17 func isPalindrome(_ charArr: [Character], from index: Int) -> Bool { 18 if index >= charArr.count { 19 return true 20 } 21 22 var left = index 23 var right = charArr.count-1 24 25 while left < right { 26 let lch = charArr[left] 27 let rch = charArr[right] 28 if lch != rch { 29 return false 30 } 31 left += 1 32 right -= 1 33 } 34 return true 35 } 36 37 func insert(_ charArr: [Character], _ index: Int, _ label: Int) -> Void { 38 // print("insert", index) 39 if index >= charArr.count { 40 self.label = label 41 return 42 } 43 44 let ch = charArr[index] 45 var node = dict[ch] 46 if node == nil { 47 node = Node() 48 dict[ch] = node 49 } 50 node?.insert(charArr, index+1, label) 51 } 52 53 func search(_ charArr: [Character], _ index: Int, _ mLabel: Int, _ labels: inout [Int]) -> Void { 54 // print("search", index) 55 if let label = label, label != mLabel { 56 if isPalindrome(charArr, from: index) == true { 57 labels.append(label) 58 } 59 } 60 61 if index >= charArr.count { 62 return 63 } 64 65 let ch = charArr[index] 66 guard let node = dict[ch] else { 67 return 68 } 69 node.search(charArr, index+1, mLabel, &labels) 70 } 71 } 72 73 var trie = Node() 74 for (i, word) in words.enumerated() { 75 trie.insert(Array(word), 0, i) 76 } 77 78 for (i, word) in words.enumerated() { 79 var labels = [Int]() 80 trie.search(Array(word.reversed()), 0, i, &labels) 81 for label in labels { 82 rslts.append([label, i]) 83 } 84 } 85 86 trie = Node() 87 for (i, word) in words.enumerated() { 88 trie.insert(Array(word.reversed()), 0, i) 89 } 90 91 for (i, word) in words.enumerated() { 92 var labels = [Int]() 93 trie.search(Array(word), 0, i, &labels) 94 for label in labels { 95 rslts.append([i, label]) 96 } 97 } 98 return Array(Set(rslts)) 99 } 100 }
4620ms
1 class Solution { 2 func palindromePairs(_ words: [String]) -> [[Int]] { 3 var wd = [String : Int]() 4 var ld = Set<Int>() 5 var res = [[Int]]() 6 for (i, word) in words.enumerated() { 7 wd[word] = i 8 ld.insert(word.count) 9 } 10 11 for i in 0 ..< words.count { 12 var word = words[i] 13 var reword = String(word.reversed()) 14 if let index = wd[reword], index != i { 15 res.append([i, index]) 16 } 17 var w1 = Array(word) 18 for l in 0 ..< w1.count { 19 if ld.contains(l) { 20 if l == 0 && isValid(w1, 0, w1.count-1) { 21 res.append([i, wd[""]!]) 22 res.append([wd[""]!, i]) 23 } else { 24 if let index = wd[String(Array(w1[0 ..< l]).reversed())], isValid(w1, l, w1.count-1) { 25 res.append([i, index]) 26 } 27 if let index = wd[String(Array(w1[w1.count-l ..< w1.count]).reversed())], isValid(w1, 0, w1.count-l-1) { 28 res.append([index, i]) 29 } 30 } 31 } 32 } 33 } 34 return res 35 } 36 37 func isValid(_ w: [Character], _ left: Int, _ right: Int) -> Bool { 38 var l = left 39 var r = right 40 while l <= r { 41 if w[l] != w[r] { 42 return false 43 } else { 44 l += 1 45 r -= 1 46 } 47 } 48 return true 49 } 50 }
7924ms
1 class Solution { 2 3 func palindromePairs(_ words: [String]) -> [[Int]] { 4 var indexes = [String: Int]() 5 var result = [[Int]]() 6 for (i, w) in words.enumerated() { 7 indexes[w] = i 8 } 9 for (i, w) in words.enumerated() { 10 for j in (0...w.count) { 11 let prefix = subword(w, 0..<j) 12 let suffix = subword(w, j..<w.count) 13 if isPalindrome(prefix) { 14 let end = String(suffix.reversed()) 15 if end != w, let index = indexes[end] { 16 result.append([index, i]) 17 } 18 } 19 if j != w.count && isPalindrome(suffix) { 20 let end = String(prefix.reversed()) 21 if end != w, let index = indexes[end] { 22 result.append([i, index]) 23 } 24 } 25 } 26 } 27 28 return result 29 } 30 31 func isPalindrome(_ word: String) -> Bool { 32 return String(word.reversed()) == word 33 } 34 35 func subword(_ word: String, _ range: Range<Int>) -> String { 36 return Array(word)[range].map { String($0) }.joined(separator: "") 37 } 38 }