[Swift]LeetCode752. 打开转盘锁 | Open the Lock
You have a lock in front of you with 4 circular wheels. Each wheel has 10 slots:? The lock initially starts at? You are given a list of? Given a? Example 1: Input: deadends = ["0201","0101","0102","1212","2002"],target = "0202" Output: 6 Explanation: A sequence of valid moves would be "0000" -> "1000" -> "1100" -> "1200" -> "1201" -> "1202" -> "0202". Note that a sequence like "0000" -> "0001" -> "0002" -> "0102" -> "0202" would be invalid,because the wheels of the lock become stuck after the display becomes the dead end "0102". Example 2: Input: deadends = ["8888"],target = "0009" Output: 1 Explanation: We can turn the last wheel in reverse to move from "0000" -> "0009".? Example 3: Input: deadends = ["8887","8889","8878","8898","8788","8988","7888","9888"],target = "8888" Output: -1 Explanation: We can‘t reach the target without getting stuck.? Example 4: Input: deadends = ["0000"],target = "8888" Output: -1? Note:
你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字:? 锁的初始数字为? 列表? 字符串? 示例 1: 输入:deadends = ["0201",target = "0202" 输出:6 解释: 可能的移动序列为 "0000" -> "1000" -> "1100" -> "1200" -> "1201" -> "1202" -> "0202"。 注意 "0000" -> "0001" -> "0002" -> "0102" -> "0202" 这样的序列是不能解锁的, 因为当拨动到 "0102" 时这个锁就会被锁定。 示例 2: 输入: deadends = ["8888"],target = "0009" 输出:1 解释: 把最后一位反向旋转一次即可 "0000" -> "0009"。 示例 3: 输入: deadends = ["8887",target = "8888" 输出:-1 解释: 无法旋转到目标数字且不被锁定。 示例 4: 输入: deadends = ["0000"],target = "8888" 输出:-1? 提示:
Runtime:?296 ms
Memory Usage:?20.1 MB
1 class Solution { 2 func openLock(_ deadends: [String],_ target: String) -> Int { 3 var start: Set<String> = [] 4 var end: Set<String> = [] 5 let deadends: Set<String> = Set(deadends) 6 7 var startToNow: Set<String> = [] 8 var endToNow: Set<String> = [] 9 10 start.insert("0000") 11 end.insert(target) 12 13 startToNow.insert("0000") 14 endToNow.insert(target) 15 16 var steps = 0 17 18 // Tip: Start from both sides 19 while !start.isEmpty && !end.isEmpty { 20 var temp: Set<String> = [] 21 22 if !start.intersection(end).isEmpty { 23 return steps 24 } 25 26 for s in start { 27 if deadends.contains(s) { continue } 28 29 for next in getNext(s) { 30 if !deadends.contains(next) && !startToNow.contains(next) { 31 temp.insert(next) 32 } 33 } 34 } 35 steps += 1 36 37 (start,end) = (end,temp) 38 (startToNow,endToNow) = (endToNow,startToNow.union(temp)) 39 } 40 41 return -1 42 } 43 44 private func getNext(_ s: String) -> Set<String> { 45 var s: [Int] = Array(s).map{ return Int(String($0))! } 46 var res: Set<String> = [] 47 48 for i in 0 ..< 4 { 49 var t = s 50 t[i] = (s[i] + 1) % 10 51 res.insert(t.reduce("",{ return $0 + String($1) })) 52 t[i] = (s[i] - 1 + 10) % 10 53 res.insert(t.reduce("",{ return $0 + String($1) })) 54 } 55 return res 56 } 57 } 560ms 1 class Solution { 2 struct Value: Hashable,CustomStringConvertible { 3 let v1: Int 4 let v2: Int 5 let v3: Int 6 let v4: Int 7 8 init(v1: Int,v2: Int,v3: Int,v4: Int) { 9 self.v1 = v1 10 self.v2 = v2 11 self.v3 = v3 12 self.v4 = v4 13 } 14 15 init(value: Int) { 16 let digits = Value.convertToDigits(number: value) 17 18 self.init(v1: digits[0],v2: digits[1],v3: digits[2],v4: digits[3]) 19 } 20 21 var nextValues: [Value] { 22 return [ 23 Value(v1: v1.incrementDecimal(),v2: v2,v3: v3,v4: v4), 24 Value(v1: v1.decrementDecimal(), 25 Value(v1: v1,v2: v2.incrementDecimal(), 26 Value(v1: v1,v2: v2.decrementDecimal(), 27 Value(v1: v1,v3: v3.incrementDecimal(), 28 Value(v1: v1,v3: v3.decrementDecimal(), 29 Value(v1: v1,v4: v4.incrementDecimal()), 30 Value(v1: v1,v4: v4.decrementDecimal()), 31 ] 32 } 33 34 var description: String { 35 return "(v1)(v2)(v3)(v4)" 36 } 37 38 private static func convertToDigits(number: Int) -> [Int] { 39 let first = number % 10 40 let second = (number % 100) / 10 41 let third = (number % 1000) / 100 42 let fourth = (number % 10000) / 1000 43 44 return [fourth,third,second,first] 45 } 46 } 47 48 class Combination: Hashable { 49 let value: Value 50 let step: Int 51 52 init(value: Value,step: Int) { 53 self.value = value 54 self.step = step 55 } 56 57 var hashValue: Int { 58 return value.hashValue 59 } 60 61 static func == (lhs: Solution.Combination,rhs: Solution.Combination) -> Bool { 62 return lhs.value == rhs.value 63 } 64 } 65 66 private var queue: [Combination] = [] 67 private var queuedValues: Set<Value> = [] 68 69 func openLock(_ deadends: [String],_ target: String) -> Int { 70 let convertedDeadends = deadends.map { Int($0)! } 71 let convertedTarget = Int(target)! 72 73 return openLock(convertedDeadends,convertedTarget) 74 } 75 76 private func openLock(_ deadends: [Int],_ target: Int) -> Int { 77 let initialCombination = Combination(value: Value(value: 0),step: 0) 78 let targetValue = Value(value: target) 79 let deadendValues = Set(deadends.map { Value(value: $0) }) 80 81 queue.append(initialCombination) 82 83 while !queue.isEmpty { 84 let combination = queue.removeFirst() 85 86 guard !deadendValues.contains(combination.value) else { continue } 87 if combination.value == targetValue { 88 return combination.step 89 } 90 91 enqueuePossibleCombinations(from: combination) 92 } 93 94 return -1 95 } 96 97 private func enqueuePossibleCombinations(from combination: Combination) { 98 let nextStep = combination.step + 1 99 100 combination.value.nextValues.forEach { 101 enqueueIfPossible(value: $0,step: nextStep) 102 } 103 } 104 105 private func enqueueIfPossible(value: Value,step: Int) { 106 guard !queuedValues.contains(value) else { return } 107 queuedValues.insert(value) 108 109 let combination = Combination(value: value,step: step) 110 queue.append(combination) 111 } 112 } 113 114 extension Int { 115 func incrementDecimal() -> Int { 116 return (self + 1) % 10 117 } 118 119 func decrementDecimal() -> Int { 120 return (self - 1 + 10) % 10 121 } 122 } 696ms 1 final class Solution { 2 3 func openLock(_ deadends: [String],_ target: String) -> Int { 4 let deadends = Set(deadends.map { str in 5 Array(str).map { Int(String($0))! } 6 }) 7 let target = Array(target).map { Int(String($0))! } 8 let start = [0,0,0] 9 var q = Queue<[Int]>() 10 var visited = Set<[Int]>() 11 q.push(start) 12 visited.insert(start) 13 var count = 0 14 while !q.isEmpty { 15 let size = q.size 16 for i in 0..<q.size { 17 let node = q.pop() 18 if deadends.contains(node) { continue } 19 if target == node { return count } 20 for (i,digit) in node.enumerated() { 21 var neighbor = node 22 neighbor[i] = (digit + 1) % 10 23 if !visited.contains(neighbor) { 24 q.push(neighbor) 25 visited.insert(neighbor) 26 } 27 neighbor = node 28 neighbor[i] = (digit - 1) 29 if neighbor[i] == -1 { neighbor[i] = 9 } 30 if !visited.contains(neighbor) { 31 q.push(neighbor) 32 visited.insert(neighbor) 33 } 34 } 35 } 36 count += 1 37 } 38 return -1 39 } 40 } 41 42 struct Queue<T> { 43 var arr = [T]() 44 var head = 0 45 46 mutating func push(_ val: T) { 47 arr.append(val) 48 } 49 50 mutating func pop() -> T { 51 let res = arr[head] 52 head += 1 53 return res 54 } 55 56 var isEmpty: Bool { 57 return head >= arr.count 58 } 59 60 var size: Int { 61 return arr.count - head 62 } 63 } 704ms 1 typealias Combo = [Int] 2 3 class Solution { 4 func openLock(_ deadends: [String],_ target: String) -> Int { 5 let target = Array(target).compactMap {Int(String($0)) } 6 let start = [0,0] 7 var seen = Set<Combo>() 8 9 for word in deadends { 10 seen.insert(Array(word).map { Int(String($0))! }) 11 } 12 guard !seen.contains(start) else { return -1 } 13 var q: [Combo] = [start] 14 var level = 0 15 16 while !q.isEmpty { 17 18 var tempQ: [Combo] = [] 19 for current in q { 20 guard current != target else { return level } 21 seen.insert(current) // add to deadends/visited list 22 23 for i in 0 ..< current.count { 24 var nextValue = current 25 nextValue[i].next() 26 27 if !seen.contains(nextValue) { 28 tempQ.append(nextValue) 29 seen.insert(nextValue) 30 } 31 32 var prevValue = current 33 prevValue[i].prev() 34 35 if !seen.contains(prevValue) { 36 tempQ.append(prevValue) 37 seen.insert(prevValue) 38 } 39 } 40 } 41 level += 1 42 q = tempQ 43 44 } 45 return -1 46 } 47 } 48 49 extension Int { 50 mutating func next() { 51 self = (self + 1) % 10 52 } 53 mutating func prev() { 54 self = (self + 10 - 1) % 10 55 } 56 } 772ms 1 class Solution { 2 func openLock(_ deadends: [String],_ target: String) -> Int { 3 let target = Array(target).map{ Int("($0)")! } 4 let deadends = Set(Array(deadends).map{ $0.map{ Int("($0)")! } }) 5 var visited = Set<[Int]>() 6 var queue = [([0,0],0)] 7 var i = 0 8 while i != queue.count { 9 let (candidate,index) = queue[i] 10 i += 1 11 if visited.contains(candidate) || deadends.contains(candidate) { continue } 12 if candidate == target { return index } 13 visited.insert(candidate) 14 for j in 0...3 { 15 var c = candidate 16 c[j] = (c[j] + 1) % 9 17 queue.append((c,index+1)) 18 } 19 for j in 0...3 { 20 var c = candidate 21 c[j] = c[j] == 0 ? 9 : c[j] - 1 22 queue.append((c,index+1)) 23 } 24 if i > 100000 { return -10000} 25 } 26 return -1 27 } 28 } 784ms 1 class Solution { 2 func openLock(_ deadends: [String],index) = queue[i] 10 i += 1 11 if visited.contains(candidate) || deadends.contains(candidate) { continue } 12 if candidate == target { return index } 13 visited.insert(candidate) 14 for j in 0...3 { 15 var c = candidate 16 var cj = c[j] 17 c[j] = (cj + 1) % 9 18 queue.append((c,index+1)) 19 c[j] = cj == 0 ? 9 : cj - 1 20 queue.append((c,index+1)) 21 } 22 } 23 return -1 24 } 25 }
Runtime:?864 ms
Memory Usage:?20.3 MB
1 class Solution { 2 func openLock(_ deadends: [String],_ target: String) -> Int { 3 var deadlock:Set<String> = Set<String>(deadends) 4 if deadlock.contains("0000") 5 { 6 return -1 7 } 8 var res:Int = 0 9 var visited:Set<String> = ["0000"] 10 var q:[String] = ["0000"] 11 while(!q.isEmpty) 12 { 13 res += 1 14 for k in stride(from:q.count,to:0,by:-1) 15 { 16 let t:String = q.removeFirst() 17 let arrChar:[Character] = Array(t) 18 let arrInt:[Int] = arrChar.map{$0.ascii} 19 for i in 0..<t.count 20 { 21 var c:Character = arrChar[i] 22 var num:Int = arrInt[i] 23 var str1:String = t.subString(0,i) + String(c == "9" ? 0 : num - 48 + 1) + t.subString(i + 1) 24 var str2:String = t.subString(0,i) + String(c == "0" ? 9 : num - 48 - 1) + t.subString(i + 1) 25 if str1 == target || str2 == target 26 { 27 return res 28 } 29 if !visited.contains(str1) && !deadlock.contains(str1) 30 { 31 q.append(str1) 32 } 33 if !visited.contains(str2) && !deadlock.contains(str2) 34 { 35 q.append(str2) 36 } 37 visited.insert(str1) 38 visited.insert(str2) 39 } 40 } 41 } 42 return -1 43 } 44 } 45 46 //Character扩展 47 extension Character 48 { 49 //Character转ASCII整数值(定义小写为整数值) 50 var ascii: Int { 51 get { 52 return Int(self.unicodeScalars.first?.value ?? 0) 53 } 54 } 55 } 56 57 extension String { 58 // 截取字符串:指定索引和字符数 59 // - begin: 开始截取处索引 60 // - count: 截取的字符数量 61 func subString(_ begin:Int,_ count:Int) -> String { 62 let start = self.index(self.startIndex,offsetBy: max(0,begin)) 63 let end = self.index(self.startIndex,offsetBy: min(self.count,begin + count)) 64 return String(self[start..<end]) 65 } 66 67 // 截取字符串:从index到结束处 68 // - Parameter index: 开始索引 69 // - Returns: 子字符串 70 func subString(_ index: Int) -> String { 71 let theIndex = self.index(self.endIndex,offsetBy: index - self.count) 72 return String(self[theIndex..<endIndex]) 73 } 74 } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |