在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ Given a list Now, we would like to merge these accounts. Two accounts definitely belong to the same person if there is some email that is common to both accounts. Note that even if two accounts have the same name, they may belong to different people as people could have the same name. A person can have any number of accounts initially, but all of their accounts definitely have the same name. After merging the accounts, return the accounts in the following format: the first element of each account is the name, and the rest of the elements are emails in sorted order. The accounts themselves can be returned in any order. Example 1: Input: accounts = [["John", "[email protected]", "[email protected]"], ["John", "[email protected]"], ["John", "[email protected]", "[email protected]"], ["Mary", "[email protected]"]] Output: [["John", '[email protected]', '[email protected]', '[email protected]'], ["John", "[email protected]"], ["Mary", "[email protected]"]] Explanation: The first and third John's are the same person as they have the common email "[email protected]". The second John and Mary are different people as none of their email addresses are used by other accounts. We could return these lists in any order, for example the answer [['Mary', '[email protected]'], ['John', '[email protected]'], ['John', '[email protected]', '[email protected]', '[email protected]']] would still be accepted. Note:
给定一个列表 现在,我们想合并这些帐户。如果两个帐户都有一些共同的邮件地址,则两个帐户必定属于同一个人。请注意,即使两个帐户具有相同的名称,它们也可能属于不同的人,因为人们可能具有相同的名称。一个人最初可以拥有任意数量的帐户,但其所有帐户都具有相同的名称。 合并帐户后,按以下格式返回帐户:每个帐户的第一个元素是名称,其余元素是按顺序排列的邮箱地址。accounts 本身可以以任意顺序返回。 例子 1: Input: accounts = [["John", "[email protected]", "[email protected]"], ["John", "[email protected]"], ["John", "[email protected]", "[email protected]"], ["Mary", "[email protected]"]] Output: [["John", '[email protected]', '[email protected]', '[email protected]'], ["John", "[email protected]"], ["Mary", "[email protected]"]] Explanation: 第一个和第三个 John 是同一个人,因为他们有共同的电子邮件 "[email protected]"。 第二个 John 和 Mary 是不同的人,因为他们的电子邮件地址没有被其他帐户使用。 我们可以以任何顺序返回这些列表,例如答案[['Mary','[email protected]'],['John','[email protected]'], ['John','[email protected]','[email protected]','[email protected]']]仍然会被接受。 注意:
552ms 1 class Solution { 2 func accountsMerge(_ accounts: [[String]]) -> [[String]] { 3 var dsu = DSU() 4 for account in accounts { 5 var emails = Array(account[1...]) 6 var name = account[0] 7 dsu.addEdge(emails, name) 8 } 9 return dsu.unions() 10 } 11 } 12 13 struct DSU { 14 var mapping: [String: Int] = [:] 15 var arr: [Int] 16 var size: [Int] 17 var comps: Int 18 var names: [Int: String] = [:] 19 20 mutating func unions() -> [[String]] { 21 var res = [String: [String]]() 22 for (email, index) in mapping { 23 let parent = find(index) 24 res["\(names[parent]!):\(parent)", default: []].append(email) 25 } 26 return res.map { arg0 in 27 var (key, val) = arg0 28 key = String(key.split(separator: ":")[0]) 29 return [key] + val.sorted() 30 } 31 } 32 33 init() { 34 arr = [] 35 size = [] 36 comps = 0 37 } 38 39 init(n: Int) { 40 comps = n 41 arr = Array(repeating: 0, count: n) 42 size = Array(repeating: 1, count: n) 43 for i in 0..<n { 44 arr[i] = i 45 } 46 } 47 48 mutating func addEdge(_ edge: [String], _ name: String) { 49 if mapping[edge[0]] == nil { 50 arr.append(arr.count) 51 size.append(1) 52 mapping[edge[0]] = arr.count - 1 53 names[arr.count - 1] = name 54 } 55 for i in 1..<edge.count { 56 if mapping[edge[i]] == nil { 57 arr.append(arr.count) 58 size.append(1) 59 mapping[edge[i]] = arr.count - 1 60 } 61 union(mapping[edge[0]]!, mapping[edge[i]]!) 62 } 63 } 64 65 mutating func find(_ a: String, _ b: String) -> Bool { 66 guard let indA = mapping[a], let indB = mapping[b] else { return false } 67 return find(indA, indB) 68 } 69 70 mutating func find(_ a: Int) -> Int { 71 return root(a) 72 } 73 74 mutating func union(_ a: Int, _ b: Int) { 75 let rootA = root(a) 76 let rootB = root(b) 77 if rootA == rootB { 78 return 79 } 80 if size[a] >= size[b] { 81 arr[rootB] = rootA 82 size[a] += size[b] 83 } else { 84 arr[rootA] = rootB 85 size[b] += size[a] 86 } 87 comps -= 1 88 } 89 90 mutating func find(_ a: Int, _ b: Int) -> Bool { 91 return root(a) == root(b) 92 } 93 94 private mutating func root(_ index: Int) -> Int { 95 var index = index 96 while arr[index] != index { 97 arr[index] = arr[arr[index]] 98 index = arr[index] 99 } 100 return index 101 } 102 } 704ms 1 class Solution { 2 class UnionManager { 3 var idMap = [String: Int]() 4 var setMap = [Int]() 5 6 func add(element: String) -> Int { 7 if idMap[element] == nil{ 8 let idForElement = setMap.count 9 idMap[element] = idForElement 10 setMap.append(idForElement) 11 } 12 return idMap[element] ?? 0 13 } 14 15 func findSet(id: Int) -> Int { 16 if setMap[id] != id { 17 setMap[id] = findSet(id: setMap[id]) 18 } 19 return setMap[id] 20 } 21 22 func union(setOf string1: String, with string2: String) { 23 let id1 = add(element: string1) 24 let id2 = add(element: string2) 25 setMap[findSet(id: id1)] = findSet(id: id2) 26 } 27 } 28 29 func accountsMerge(_ accounts: [[String]]) -> [[String]] { 30 let unionManager = UnionManager() 31 var emailToName = [String: String]() 32 let nonEmptyAccounts = accounts.filter{ $0.count > 1 } 33 for account in nonEmptyAccounts { 34 let name = account[0] 35 for email in account[1..<account.count] { 36 emailToName[email] = name 37 unionManager.union(setOf: email, with: account[1]) 38 } 39 } 40 var results: [Int: [String]] = [:] 41 for (email, id) in unionManager.idMap { 42 let setId = unionManager.findSet(id: id) 43 results[setId, default: []].append(email) 44 } 45 return results.values.map { $0.sorted() } 46 .map { emailList in 47 if let name = emailToName[emailList[0]] { 48 return [name] + emailList 49 } else { 50 return emailList 51 } 52 } 53 } 54 } 732ms 1 class Solution { 2 func accountsMerge(_ accounts: [[String]]) -> [[String]] { 3 guard accounts.count > 0 else { 4 return [] 5 } 6 let graph = Graph<String>(.undirected) 7 var emailToNameDictionary: [String: String] = [:] 8 for account in accounts { 9 let name = account[0] 10 let source = graph.createVertex(account[1]) 11 for i in 1..<account.count { 12 let email = account[i] 13 emailToNameDictionary[email] = name 14 if i > 1 { 15 let destination = graph.createVertex(account[i]) 16 graph.addUndirectedEdge(between: source, and: destination) 17 } 18 } 19 } 20 var mergedAccounts: [[String]] = [] 21 var discovered: Set<Vertex<String>> = [] 22 for vertex in graph.vertice { 23 if !discovered.contains(vertex) { 24 var emails: [String] = [] 25 depthFirstSearch(graph, vertex, &discovered, &emails) 26 let result = [emailToNameDictionary[vertex.val]!] + emails.sorted() 27 mergedAccounts.append(result) 28 } 29 } 30 31 return mergedAccounts 32 } 33 } 34 35 func depthFirstSearch<T: Hashable>(_ graph: Graph<T>, 36 _ source: Vertex<T>, 37 _ discovered: inout Set<Vertex<T>>, 38 _ emails: inout [T] 39 ) { 40 discovered.insert(source) 41 emails.append(source.val) 42 for edge in graph.edges(of: source) { 43 let destination = edge.destination 44 if !discovered.contains(destination) { 45 depthFirstSearch(graph, destination, &discovered, &emails) 46 } 47 } 48 } 49 50 51 enum GraphType { 52 case directed 53 case undirected 54 } 55 56 struct Vertex<T: Hashable>: Hashable { 57 public var val: T 58 public init(_ val: T) { 59 self.val = val 60 } 61 62 public var hashValue : Int { 63 return val.hashValue 64 } 65 66 public static func ==(lhs: Vertex<T>, rhs: Vertex<T>) -> Bool { 67 return lhs.val == rhs.val 68 } 69 } 70 71 struct Edge<T: Hashable> { 72 public let source: Vertex<T> 73 public let destination: Vertex<T> 74 public let weight: Double? 75 public init(source: Vertex<T>, destination: Vertex<T>, weight: Double? = nil ) { 76 self.source = source 77 self.destination = destination 78 self.weight = weight 79 } 80 } 81 82 83 class Graph<T: Hashable> { 84 public var vertice: [Vertex<T>] = [] 85 private var adjacencyList: [Vertex<T>: [Edge<T>]] = [:] 86 public var type: GraphType 87 88 public init(_ type: GraphType) { 89 self.type = type 90 } 91 92 public func createVertex(_ val: T) -> Vertex<T> { 93 let source = Vertex(val) 94 if adjacencyList[source] == nil { 95 adjacencyList[source] = [] 96 vertice.append(source) 97 } 98 return source 99 } 100 101 public func addDirectedEdge(from source: Vertex<T>, 102 to destination: Vertex<T>, 103 weight: Double? = nil 104 ) { 105 let edge = Edge(source: source, destination: destination, weight: weight) 106 adjacencyList[source]?.append(edge) 107 } 108 109 public func addUndirectedEdge(between source: Vertex<T>, 110 and destination: Vertex<T>, 111 weight: Double? = nil 112 ) { 113 addDirectedEdge(from: source, to: destination, weight: weight) 114 addDirectedEdge(from: destination, to: source, weight: weight) 115 } 116 117 public func edges(of source: Vertex<T>) -> [Edge<T>] { 118 return adjacencyList[source] ?? [] 119 } 120 121 public func weight(from source: Vertex<T>, 122 to destination: Vertex<T> 123 ) -> Double? { 124 return adjacencyList[source]?.first{ $0.destination == destination }?.weight 125 } 126 } 852ms 1 class Solution { 2 // father[儿子] = 老大哥 3 var father = [Int: Int]() 4 5 func accountsMerge(_ accounts: [[String]]) -> [[String]] { 6 7 // 1 union 8 let emailToID = getEmailToID(accounts) 9 for email in emailToID.keys { 10 let ids = emailToID[email]! 11 for i in ids { 12 union(i, ids[0]) 13 } 14 } 15 16 //2 merge 17 let idToEmailSet = getIdToEmailSet(accounts) 18 var mergedAccounts = [[String]]() 19 20 for id in idToEmailSet.keys { 21 var sortedEmails = idToEmailSet[id]!.sorted() 22 sortedEmails.insert(accounts[id][0], at: 0) 23 mergedAccounts.append(sortedEmails) 24 } 25 26 return mergedAccounts 27 } 28 29 //find -> 找老大哥 30 func find(_ id: Int) -> Int { 31 var id = id 32 33 var path = [Int]() 34 while let nextID = father[id] { 35 path.append(id) 36 id = nextID 37 38 } 39 40 for i in path { 41 father[i] = id 42 } 43 44 return id 45 } 46 47 // union 48 func union(_ a: Int, _ b: Int) { 49 let rootA = find(a) 50 let rootB = find(b) 51 if rootA != rootB { 52 father[rootA] = rootB 53 } 54 } 55 56 57 // 这个只是data处理 58 func getEmailToID(_ accounts: [[String]]) -> [String: [Int]] { 59 var emailToID = [String: [Int]]() 60 61 for (userID, acnt) in accounts.enumerated() { 62 for i in 1..<acnt.count { 63 let curEmail = acnt[i] 64 var ids = emailToID[curEmail, default: [Int]()] 65 ids.append(userID) 66 emailToID[curEmail] = ids 67 } 68 } 69 70 return emailToID 71 } 72 73 func getIdToEmailSet(_ accounts: [[String]]) -> [Int: Set<String>] { 74 var idToEmailSet = [Int: Set<String>]() 75 for id in 0..<accounts.count { 76 let root_id = find(id) 77 var emailSet = idToEmailSet[root_id, default: Set<String>()] 78 79 let account = accounts[id] 80 for i in 1..<account.count { 81 emailSet.insert(account[i]) 82 } 83 idToEmailSet[root_id] = emailSet 84 } 85 86 return idToEmailSet 87 } 88 } 864ms 1 class Solution { 2 func accountsMerge(_ accounts: [[String]]) -> [[String]] { 3 guard accounts.count > 0 else { 4 return [] 5 } 6 7 var emailToName: [String: String] = [:] 8 var unionFind = UnionFind<String>() 9 for account in accounts { 10 let name = account[0] 11 let firstEmail = account[1] 12 unionFind.addSet(firstEmail) 13 for i in 1..<account.count { 14 let email = account[i] 15 emailToName[email] = name 16 17 if i > 1 { 18 let email = account[i] 19 unionFind.addSet(email) 20 unionFind.union(firstEmail, email) 21 } 22 } 23 } 24 25 var mergedAccount: [[String]] = [] 26 var storage: [Int: [String]] = [:] 27 for element in unionFind.index.keys { 28 let parentIndex = unionFind.find(element)! 29 if storage[parentIndex] == nil { 30 storage[parentIndex] = [element] 31 } else { 32 storage[parentIndex]!.append(element) 33 } 34 } 35 36 for emails in storage.values { 37 let name = emailToName[emails.first!]! 38 |
请发表评论