[Swift]LeetCode767. 重构字符串 | Reorganize String
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址: https://www.cnblogs.com/strengthen/p/10534876.html
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
Given a string S
, check if the letters can be rearranged so that two characters that are adjacent to each other are not the same.
If possible, output any possible result. If not possible, return the empty string.
Example 1:
Input: S = "aab" Output: "aba"
Example 2:
Input: S = "aaab" Output: ""
Note:
S
will consist of lowercase letters and have length in range[1, 500]
.
给定一个字符串S
,检查是否能重新排布其中的字母,使得两相邻的字符不同。
若可行,输出任意可行的结果。若不可行,返回空字符串。
示例 1:
输入: S = "aab" 输出: "aba"
示例 2:
输入: S = "aaab" 输出: ""
注意:
S
只包含小写字母并且长度在[1, 500]
区间内。
Runtime: 12 ms
Memory Usage: 20.2 MB
1 class Solution { 2 func reorganizeString(_ S: String) -> String { 3 var n:Int = S.count 4 var idx:Int = 1 5 var cnt:[Int] = [Int](repeating:0,count:26) 6 var arrChar:[Character] = Array(S) 7 for char in S.characters 8 { 9 cnt[char.ascii - 97] += 100 10 } 11 for i in 0..<26 12 { 13 cnt[i] += i 14 } 15 cnt.sort() 16 for num in cnt 17 { 18 var t:Int = num / 100 19 var ch:Character = (97 + (num % 100)).ASCII 20 if t > (n + 1) / 2 {return String()} 21 for i in 0..<t 22 { 23 if idx >= n {idx = 0} 24 arrChar[idx] = ch 25 idx += 2 26 } 27 } 28 return String(arrChar) 29 } 30 } 31 32 //Character扩展 33 extension Character 34 { 35 //Character转ASCII整数值(定义小写为整数值) 36 var ascii: Int { 37 get { 38 return Int(self.unicodeScalars.first?.value ?? 0) 39 } 40 } 41 } 42 43 //Int扩展 44 extension Int 45 { 46 //Int转Character,ASCII值(定义大写为字符值) 47 var ASCII:Character 48 { 49 get {return Character(UnicodeScalar(self)!)} 50 } 51 }
12ms
1 class Solution { 2 func reorganizeString(_ s: String) -> String { 3 let n = s.count 4 var counts = [Int](repeating: 0, count: 26) 5 for character in s { 6 let index: Int = Int(character.unicodeScalars.first!.value - "a".unicodeScalars.first!.value) 7 counts[index] += 100 8 } 9 for i in 0..<counts.count { 10 counts[i] += i 11 } 12 counts = counts.sorted(by: >) 13 14 var output = [Character](repeating: " ", count:n) 15 var j = 0 16 for code in counts { 17 let count = code / 100 18 let charValue = Int("a".unicodeScalars.first!.value) + (code % 100) 19 let unicode = UnicodeScalar(charValue)! 20 let char = Character(unicode) 21 guard count <= (n + 1) / 2 else { 22 return "" 23 } 24 25 for i in 0..<count { 26 if (j >= n) { 27 j = 1 28 } 29 output[j] = char 30 j += 2 31 } 32 } 33 34 return String(output) 35 } 36 }
16ms
1 class Solution { 2 func reorganizeString(_ S: String) -> String { 3 var s = Array(S.utf8) 4 var counts = [Int](repeating: 0, count: 26) 5 for u in s { 6 counts[Int(u) - 97] += 1 7 } 8 var res = [Character]() 9 var lastIndex = -1 10 while res.count != s.count { 11 guard let index = maxIndex(counts, lastIndex) else { 12 return "" 13 } 14 counts[index] -= 1 15 lastIndex = index 16 res.append(Character(UnicodeScalar(index + 97)!)) 17 } 18 return String(res) 19 } 20 21 private func maxIndex(_ counts: [Int], _ notIndex: Int) -> Int? { 22 var maxC = 0 23 var retVal = -1 24 for i in 0..<26 { 25 if i != notIndex && counts[i] > maxC { 26 retVal = i 27 maxC = counts[i] 28 } 29 } 30 return retVal == -1 ? nil : retVal 31 } 32 }
24ms
1 class Solution { 2 func reorganizeString(_ string: String) -> String { 3 4 // we only care about the character counts, and not how the string is constructed 5 let characterToCount = string.reduce(into: [:], { $0[$1, default: 0] += 1 }) 6 7 var maxHeap = Heap<(character: Character, count: Int)>( 8 array: characterToCount.map { $0 }, 9 sort: { $0.count > $1.count }) 10 11 var newString = "" 12 13 while let maxPair = maxHeap.remove() { 14 15 // we can use the maxPair `character` 16 if newString.last != maxPair.character { 17 18 newString.append(maxPair.character) 19 20 if maxPair.count > 1 { 21 maxHeap.insert((maxPair.character, maxPair.count-1)) 22 } 23 } else if let nextMaxPair = maxHeap.remove() { 24 25 newString.append(nextMaxPair.character) 26 27 if nextMaxPair.count > 1 { 28 maxHeap.insert((nextMaxPair.character, nextMaxPair.count-1)) 29 } 30 maxHeap.insert(maxPair) 31 } else { 32 return "" // we can't find any character to place in next 33 } 34 } 35 36 return newString 37 } 38 } 39 40 public struct Heap<T> { 41 var elements = [T]() 42 fileprivate var isOrderedBefore: (T, T) -> Bool 43 public init(sort: @escaping (T, T) -> Bool) { 44 self.isOrderedBefore = sort 45 } 46 public init(array: [T], sort: @escaping (T, T) -> Bool) { 47 self.isOrderedBefore = sort 48 buildHeap(fromArray: array) 49 } 50 fileprivate mutating func buildHeap(fromArray array: [T]) { 51 elements = array 52 for i in stride(from: (elements.count/2 - 1), through: 0, by: -1) { 53 shiftDown(i, heapSize: elements.count) 54 } 55 } 56 public var isEmpty: Bool { 57 return elements.isEmpty 58 } 59 60 public var count: Int { 61 return elements.count 62 } 63 @inline(__always) func parentIndex(ofIndex i: Int) -> Int { 64 return (i - 1) / 2 65 } 66 @inline(__always) func leftChildIndex(ofIndex i: Int) -> Int { 67 return 2*i + 1 68 } 69 @inline(__always) func rightChildIndex(ofIndex i: Int) -> Int { 70 return 2*i + 2 71 } 72 public func peek() -> T? { 73 return elements.first 74 } 75 public mutating func insert(_ value: T) { 76 elements.append(value) 77 shiftUp(elements.count - 1) 78 } 79 public mutating func insert<S: Sequence>(_ sequence: S) where S.Iterator.Element == T { 80 for value in sequence { 81 insert(value) 82 } 83 } 84 public mutating func replace(index i: Int, value: T) { 85 guard i < elements.count else { return } 86 87 assert(isOrderedBefore(value, elements[i])) 88 elements[i] = value 89 shiftUp(i) 90 } 91 @discardableResult public mutating func remove() -> T? { 92 if elements.isEmpty { 93 return nil 94 } else if elements.count == 1 { 95 return elements.removeLast() 96 } else { 97 // Use the last node to replace the first one, then fix the heap by 98 // shifting this new first node into its proper position. 99 let value = elements[0] 100 elements[0] = elements.removeLast() 101 shiftDown() 102 return value 103 } 104 } 105 public mutating func removeAt(_ index: Int) -> T? { 106 guard index < elements.count else { return nil } 107 108 let size = elements.count - 1 109 if index != size { 110 elements.swapAt(index, size) 111 // swap(&elements[index], &elements[size]) 112 shiftDown(index, heapSize: size) 113 shiftUp(index) 114 } 115 return elements.removeLast() 116 } 117 mutating func shiftUp(_ index: Int) { 118 var childIndex = index 119 let child = elements[childIndex] 120 var parentIndex = self.parentIndex(ofIndex: childIndex) 121 122 while childIndex > 0 && isOrderedBefore(child, elements[parentIndex]) { 123 elements[childIndex] = elements[parentIndex] 124 childIndex = parentIndex 125 parentIndex = self.parentIndex(ofIndex: childIndex) 126 } 127 128 elements[childIndex] = child 129 } 130 mutating func shiftDown() { 131 shiftDown(0, heapSize: elements.count) 132 } 133 mutating func shiftDown(_ index: Int, heapSize: Int) { 134 var parentIndex = index 135 136 while true { 137 let leftChildIndex = self.leftChildIndex(ofIndex: parentIndex) 138 let rightChildIndex = leftChildIndex + 1 139 var first = parentIndex 140 if leftChildIndex < heapSize && isOrderedBefore(elements[leftChildIndex], elements[first]) { 141 first = leftChildIndex 142 } 143 if rightChildIndex < heapSize && isOrderedBefore(elements[rightChildIndex], elements[first]) { 144 first = rightChildIndex 145 } 146 if first == parentIndex { return } 147 148 elements.swapAt(parentIndex, first) 149 // swap(&elements[parentIndex], &elements[first]) 150 parentIndex = first 151 } 152 } 153 } 154 extension Heap where T: Equatable { 155 public func index(of element: T) -> Int? { 156 return index(of: element, 0) 157 } 158 fileprivate func index(of element: T, _ i: Int) -> Int? { 159 if i >= count { return nil } 160 if isOrderedBefore(element, elements[i]) { return nil } 161 if element == elements[i] { return i } 162 if let j = index(of: element, self.leftChildIndex(ofIndex: i)) { return j } 163 if let j = index(of: element, self.rightChildIndex(ofIndex: i)) { return j } 164 return nil 165 } 166 }
36ms
1 class Solution { 2 func reorganizeString(_ S: String) -> String { 3 var mapy = [Character: Int]() 4 for c in S { 5 mapy[c, default: 0] += 1 6 } 7 let heap = Heap<(Character, Int)>(elements: mapy.map { ($0.0,$0.1) }, priority: { 8 return $0.1 > $1.1 9 }) 10 var arr = [Character]() 11 while heap.isEmpty == false { 12 var top = heap.dequeue()! 13 if arr.last == top.0 { 14 if var second = heap.dequeue() { 15 arr.append(second.0) 16 second.1 -= 1 17 if top.1 > 0 { 18 heap.enqueue(top) 19 } 20 if second.1 > 0 { 21 heap.enqueue(second) 22 } 23 } else { 24 return "" 25 } 26 } else { 27 arr.append(top.0) 28 top.1 -= 1 29 if top.1 > 0 { 30 heap.enqueue(top) 31 } 32 } 33 } 34 return String(arr) 35 } 36 } 37 38 final class Heap<T> { 39 40 typealias Comparator = (T,T) -> Bool 41 42 var elements: [T] 43 let priority: Comparator 44 45 init(elements: [T], priority: @escaping Comparator) { 46 self.priority = priority 47 self.elements = elements 48 if elements.isEmpty == false { 49 for i in stride(from: (count / 2) - 1, to: -1, by: -1) { 50 siftDown(i) 51 } 52 } 53 } 54 55 var isEmpty: Bool { 56 return elements.isEmpty 57 } 58 59 var count: Int { 60 return elements.count 61 } 62 63 var first: T? { 64 return elements.first 65 } 66 67 func leftChildIndex(of index: Int) -> Int { 68 return (2 * index) + 1 69 } 70 71 func rightChild(of index: Int) -> Int { 72 return (2 * index) + 2 73 } 74 75 func parentIndex(of index: Int) -> Int { 76 return (index - 1) / 2 77 } 78 79 func isHigherPriority(_ a: Int, _ b: Int) -> Bool { 80 return priority(elements[a], elements[b]) 81 } 82 83 func highestPriorityIndex(of index: Int) -> Int { 84 let left = highestPriorityIndex(of: index, and: leftChildIndex(of: index)) 85 let right = highestPriorityIndex(of: index, and: rightChild(of: index)) 86 return highestPriorityIndex(of: left, and: right) 87 } 88 89 func highestPriorityIndex(of parent: Int, and child: Int) -> Int { 90 guard child < count else { 91 return parent 92 } 93 guard isHigherPriority(child, parent) else { 94 return parent 95 } 96 return child 97 } 98 99 func enqueue(_ element: T) { 100 elements.append(element) 101 siftUp(count - 1) 102 } 103 104 func siftUp(_ i: Int) { 105 let parent = parentIndex(of: i) 106 guard parent >= 0 else { 107 return 108 } 109 guard isHigherPriority(i, parent) else { 110 return 111 } 112 swap(i, parent) 113 siftUp(parent) 114 } 115 116 func dequeue() -> T? { 117 guard count > 0 else { 118 return nil 119 } 120 return remove(at: 0) 121 } 122 123 func remove(at i: Int) -> T? { 124 swap(i, count - 1) 125 let element = elements.popLast() 126 siftDown(i) 127 return element 128 } 129 130 fileprivate func swap(_ i: Int, _ j: Int) { 131 (elements[i], elements[j]) = (elements[j], elements[i]) 132 } 133 134 func siftDown(_ i: Int) { 135 let indexToSwap = highestPriorityIndex(of: i) 136 guard indexToSwap != i else { 137 return 138 } 139 swap(indexToSwap, i) 140 siftDown(indexToSwap) 141 } 142 }
40ms
1 class Solution { 2 func reorganizeString(_ S: String) -> String { 3 var countByChar = [Character:Int]() 4 for c in Array(S) { 5 countByChar[c, default:0] += 1 6 } 7 var chars = countByChar.keys.sorted { 8 return countByChar[$0]! > countByChar[$1]! 9 } 10 var t = 0 11 var result = Array(repeating: Character("~"), count: S.count) 12 for c in chars { 13 for _ in 0..<countByChar[c]! { 14 if countByChar[c]! > (S.count + 1) / 2 { 15 return "" 16 } 17 if t >= S.count { 18 t = 1 19 } 20 result[t] = c 21 t += 2 22 } 23 } 24 25 return String(result) 26 } 27 }
48ms
1 class Solution { 2 func reorganizeString(_ S: String) -> String { 3 typealias Pair = (key: Character, value: Int) 4 let s = S 5 if s.count < 1 { return "" } 6 var dict = [Character: Int]() 7 // var heap = Heap<Pair> { $0.value > $1.value } 8 var sorted = [Pair]() 9 var queue = [Pair]() 10 var result = "" 11 12 for c in s { 13 dict[c] = (dict[c] ?? 0) + 1 14 } 15 16 // dict.forEach { 17 // heap.add($0) 18 // } 19 sorted = dict.sorted { $0.value > $1.value }.map { $0 } 20 21 while sorted.count > 0 { 22 let top = sorted.removeFirst() 23 result += String(top.key) 24 25 let count = top.value - 1 26 queue.append((top.key, count)) 27 28 if queue.count > 1 { 29 let first = queue.removeFirst() 30 if first.value > 0 { 31 sorted.append(first) 32 sorted = sorted.sorted { $0.value > $1.value } 33 } 34 } 35 } 36 37 if result.count != s.count { 38 return "" 39 } 40 41 return result 42 } 43 }
56ms
1 class Solution { 2 func reorganizeString(_ S: String) -> String { 3 var countByChar = Dictionary<Character, Int>(minimumCapacity:26) 4 for c in Array(S) { 5 countByChar[c, default:0] += 1 6 } 7 var chars = countByChar.keys.sorted { 8 return countByChar[$0]! > countByChar[$1]! 9 } 10 var t = 0 11 var result = Array(repeating: Character("~"), count: S.count) 12 for c in chars { 13 for _ in 0..<countByChar[c]! { 14 if countByChar[c]! > (S.count + 1) / 2 { 15 return "" 16 } 17 if t >= S.count { 18 t = 1 19 } 20 result[t] = c 21 t += 2 22 } 23 } 24 25 return String(result) 26 } 27 }
68ms
1 import Foundation 2 3 public struct Heap<T> { 4 5 /** The array that stores the heap's nodes. */ 6 var nodes = [T]() 7 8 /** 9 * Determines how to compare two nodes in the heap. 10 * Use '>' for a max-heap or '<' for a min-heap, 11 * or provide a comparing method if the heap is made 12 * of custom elements, for example tuples. 13 */ 14 private var orderCriteria: (T, T) -> Bool 15 16 /** 17 * Creates an empty heap. 18 * The sort function determines whether this is a min-heap or max-heap. 19 * For comparable data types, > makes a max-heap, < makes a min-heap. 20 */ 21 public init(sort: @escaping (T, T) -> Bool) { 22 self.orderCriteria = sort 23 } 24 25 /** 26 * Creates a heap from an array. The order of the array does not matter; 27 * the elements are inserted into the heap in the order determined by the 28 * sort function. For comparable data types, '>' makes a max-heap, 29 * '<' makes a min-heap. 30 */ 31 public init(array: [T], sort: @escaping (T, T) -> Bool) { 32 self.orderCriteria = sort 33 configureHeap(from: array) 34 } 35 36 /** 37 * Configures the max-heap or min-heap from an array, in a bottom-up manner. 38 * Performance: This runs pretty much in O(n). 39 */ 40 private mutating func configureHeap(from array: [T]) { 41 nodes = array 42 for i in stride(from: (nodes.count/2-1), through: 0, by: -1) { 43 shiftDown(i) 44 } 45 } 46 47 public var isEmpty: Bool { 48 return nodes.isEmpty 49 } 50 51 public var count: Int { 52 return nodes.count 53 } 54 55 /** 56 * Returns the index of the parent of the element at index i. 57 * The element at index 0 is the root of the tree and has no parent. 58 */ 59 @inline(__always) internal func parentIndex(ofIndex i: Int) -> Int { 60 return (i - 1) / 2 61 } 62 63 /** 64 * Returns the index of the left child of the element at index i. 65 * Note that this index can be greater than the heap size, in which case 66 * there is no left child. 67 */ 68 @inline(__always) internal func leftChildIndex(ofIndex i: Int) -> Int { 69 return 2*i + 1 70 } 71 72 /** 73 * Returns the index of the right child of the element at index i. 74 * Note that this index can be greater than the heap size, in which case 75 * there is no right child. 76 */ 77 @inline(__always) internal func rightChildIndex(ofIndex i: Int) -> Int { 78 return 2*i + 2 79 } 80 81 /** 82 * Returns the maximum value in the heap (for a max-heap) or the minimum 83 * value (for a min-heap). 84 */ 85 public func peek() -> T? { 86 return nodes.first 87 } 88 89 /** 90 * Adds a new value to the heap. This reorders the heap so that the max-heap 91 * or min-heap property still holds. Performance: O(log n). 92 */ 93 public mutating func insert(_ value: T) { 94 nodes.append(value) 95 shiftUp(nodes.count - 1) 96 } 97 98 /** 99 * Adds a sequence of values to the heap. This reorders the heap so that 100 * the max-heap or min-heap property still holds. Performance: O(log n). 101 */ 102 public mutating func insert<S: Sequence>(_ sequence: S) where S.Iterator.Element == T { 103 for value in sequence { 104 insert(value) 105 } 106 } 107 108 /** 109 * Allows you to change an element. This reorders the heap so that 110 * the max-heap or min-heap property still holds. 111 */ 112 public mutating func replace(index i: Int, value: T) { 113 guard i < nodes.count else { return } 114 115 remove(at: i) 116 insert(value) 117 } 118 119 /** 120 * Removes the root node from the heap. For a max-heap, this is the maximum 121 * value; for a min-heap it is the minimum value. Performance: O(log n). 122 */ 123 @discardableResult public mutating func remove() -> T? { 124 guard !nodes.isEmpty else { return nil } 125 126 if nodes.count == 1 { 127 return nodes.removeLast() 128 } else { 129 // Use the last node to replace the first one, then fix the heap by 130 // shifting this new first node into its proper position. 131 let value = nodes[0] 132 nodes[0] = nodes.removeLast() 133 shiftDown(0) 134 return value 135 } 136 } 137 138 /** 139 * Removes an arbitrary node from the heap. Performance: O(log n). 140 * Note that you need to know the node's index. 141 */ 142 @discardableResult public mutating func remove(at index: Int) -> T? { 143 guard index < nodes.count else { return nil } 144 145 let size = nodes.count - 1 146 if index != size { 147 nodes.swapAt(index, size) 148 shiftDown(from: index, until: size) 149 shiftUp(index) 150 } 151 return nodes.removeLast() 152 } 153 154 /** 155 * Takes a child node and looks at its parents; if a parent is not larger 156 * (max-heap) or not smaller (min-heap) than the child, we exchange them. 157 */ 158 internal mutating func shiftUp(_ index: Int) { 159 var childIndex = index 160 let child = nodes[childIndex] 161 var parentIndex = self.parentIndex(ofIndex: childIndex) 162 163 while childIndex > 0 && orderCriteria(child, nodes[parentIndex]) { 164 nodes[childIndex] = nodes[parentIndex] 165 childIndex = parentIndex 166 parentIndex = self.parentIndex(ofIndex: childIndex) 167 } 168 169 nodes[childIndex] = child 170 } 171 172 /** 173 * Looks at a parent node and makes sure it is still larger (max-heap) or 174 * smaller (min-heap) than its childeren. 175 */ 176 internal mutating func shiftDown(from index: Int, until endIndex: Int) { 177 let leftChildIndex = self.leftChildIndex(ofIndex: index) 178 let rightChildIndex = leftChildIndex + 1 179 180 // Figure out which comes first if we order them by the sort function: 181 // the parent, the left child, or the right child. If the parent comes 182 // first, we're done. If not, that element is out-of-place and we make 183 // it "float down" the tree until the heap property is restored. 184 var first = index 185 if leftChildIndex < endIndex && orderCriteria(nodes[leftChildIndex], nodes[first]) { 186 first = leftChildIndex 187 } 188 if rightChildIndex < endIndex && orderCriteria(nodes[rightChildIndex], nodes[first]) { 189 first = rightChildIndex 190 } 191 if first == index { return } 192 193 nodes.swapAt(index, first) 194 shiftDown(from: first, until: endIndex) 195 } 196 197 internal mutating func shiftDown(_ index: Int) { 198 shiftDown(from: index, until: nodes.count) 199 } 200 201 } 202 203 extension Heap where T: Equatable { 204 205 /** Get the index of a node in the heap. Performance: O(n). */ 206 public func index(of node: T) -> Int? { 207 return nodes.index(where: { $0 == node }) 208 } 209 210 /** Removes the first occurrence of a node from the heap. Performance: O(n log n). */ 211 @discardableResult public mutating func remove(node: T) -> T? { 212 if let index = index(of: node) { 213 return remove(at: index) 214 } 215 return nil 216 } 217 218 } 219 220 /* 221 Priority Queue, a queue where the most "important" items are at the front of 222 the queue. 223 The heap is a natural data structure for a priority queue, so this object 224 simply wraps the Heap struct. 225 All operations are O(lg n). 226 Just like a heap can be a max-heap or min-heap, the queue can be a max-priority 227 queue (largest element first) or a min-priority queue (smallest element first). 228 */ 229 public struct PriorityQueue<T> { 230 fileprivate var heap: Heap<T> 231 232 /* 233 To create a max-priority queue, supply a > sort function. For a min-priority 234 queue, use <. 235 */ 236 public init(sort: @escaping (T, T) -> Bool) { 237 heap = Heap(sort: sort) 238 } 239 240 public var isEmpty: Bool { 241 return heap.isEmpty 242 } 243 244 public var count: Int { 245 return heap.count 246 } 247 248 public func peek() -> T? { 249 return heap.peek() 250 } 251 252 public mutating func enqueue(_ element: T) { 253 heap.insert(element) 254 } 255 256 public mutating func dequeue() -> T? { 257 return heap.remove() 258 } 259 260 /* 261 Allows you to change the priority of an element. In a max-priority queue, 262 the new priority should be larger than the old one; in a min-priority queue 263 it should be smaller. 264 */ 265 public mutating func changePriority(index i: Int, value: T) { 266 return heap.replace(index: i, value: value) 267 } 268 } 269 270 extension PriorityQueue where T: Equatable { 271 public func index(of element: T) -> Int? { 272 return heap.index(of: element) 273 } 274 275 public mutating func dequeue(element: T) -> T? { 276 guard peek() != nil else { return nil } 277 let indexToDequeue = index(of: element)! 278 changePriority(index: indexToDequeue, value: peek()!) 279 return dequeue() 280 } 281 } 282 283 class Solution { 284 func reorganizeString(_ S: String) -> String { 285 guard S.count != 0 else { return "" } 286 287 // Store char frequency pair into map 288 var map = [Character: Int]() 289 290 for character in S { 291 map[character] = (map[character] ?? 0) + 1 292 } 293 294 // push all map entry into priority element, by sorting from high frequency to low frequency. Max Priority queue where highest frequeny elements are first 295 var pq = PriorityQueue<(Character, Int)> { (a, b) -> Bool in 296 return a.1 > b.1 297 } 298 for (key, value) in map { 299 pq.enqueue((key, value)) 300 } 301 302 var result = "" 303 304 while !pq.isEmpty { 305 // store character with the highest frequency in cache 306 var cache = pq.dequeue()! 307 let resultsArray = Array(result) 308 309 // if character in cache is different from tail character in current string 310 if result.count == 0 || cache.0 != resultsArray.last { 311 result.append(cache.0) 312 cache.1 -= 1 313 314 // if the current character still have more frequencies left, push to q 315 if cache.1 > 0 { 316 pq.enqueue(cache) 317 } 318 } 319 // if character in cache is same as tail character in current string 320 // we need to try the character with second highest frequency 321 else { 322 var cache2 = pq.dequeue() 323 // corner case: if no more elements in queue, the input string should be invalid 324 // because we do not have any other characters that different with current string tail 325 if cache2 == nil { 326 return "" 327 } 328 329 result.append(cache2!.0) 330 cache2!.1 -= 1 331 332 // if current character still have mor efrequencies left, push to q 333 // if the current character still have more frequencies left, push to q 334 if cache2!.1 > 0 { 335 pq.enqueue(cache2!) 336 } 337 338 //Push top freqeuncy entry into queue as well 339 pq.enqueue(cache) 340 } 341 } 342 return result 343 } 344 }
96ms
1 class Solution { 2 func reorganizeString(_ S: String) -> String { 3 guard S.count > 2 && S.count <= 500 else { 4 return S.count > 0 && S.count <= 2 ? S : "" 5 } 6 var dict = [Character: Int]() 7 for char in Array(S) { 8 if let count = dict[char] { 9 dict[char] = count + 1 10 } else { 11 dict[char] = 1 12 } 13 } 14 var sortedCharInfos = dict.sorted { 15 $0.1 >= $1.1 16 } 17 if let firstCharInfo = sortedCharInfos.first, firstCharInfo.1 > (S.count + 1) / 2 { 18 return "" 19 } 20 var result = "" 21 func addChar(_ index: Int) { 22 guard index < sortedCharInfos.count else { 23 return 24 } 25 let firstCharInfo = sortedCharInfos[index] 26 result.append(firstCharInfo.key) 27 if sortedCharInfos[index].value == 1 { 28 sortedCharInfos.remove(at: index) 29 } else { 30 sortedCharInfos[index] = (firstCharInfo.key, firstCharInfo.value - 1) 31 } 32 } 33 while !sortedCharInfos.isEmpty { 34 if let lastChar = result.last { 35 sortedCharInfos.sort { 36 $0.1 >= $1.1 37 } 38 if lastChar == sortedCharInfos.first!.key { 39 addChar(1) 40 } else { 41 addChar(0) 42 } 43 } else { 44 addChar(0) 45 } 46 } 47 return result 48 } 49 }