You have a lock in front of you with 4 circular wheels. Each wheel has 10 slots: ‘0‘,‘1‘,‘2‘,‘3‘,‘4‘,‘5‘,‘6‘,‘7‘,‘8‘,‘9‘
. The wheels can rotate freely and wrap around: for example we can turn ‘9‘
to be ‘0‘
,or ‘0‘
to be ‘9‘
. Each move consists of turning one wheel one slot.
The lock initially starts at ‘0000‘
,a string representing the state of the 4 wheels.
You are given a List of deadends
dead ends,meaning if the lock displays any of these codes,the wheels of the lock will stop turning and you will be unable to open it.
Given a target
representing the value of the wheels that will unlock the lock,return the minimum total number of turns required to open the lock,or -1 if it is impossible.
Example 1:
input: deadends = ["0201","0101","0102","1212","2002"],target = "0202"Output: 6Explanation: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: 1Explanation: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: -1Explanation:We can‘t reach the target without getting stuck.
Example 4:
input: deadends = ["0000"],target = "8888"Output: -1
Note:
The length ofdeadends
will be in the range [1,500]
. target
will not be in the List deadends
. Every string in deadends
and the string target
will be a string of 4 digits from the 10,000 possibilitIEs ‘0000‘
to ‘9999‘
. 你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字: ‘0‘,‘9‘
。每个拨轮可以自由旋转:例如把 ‘9‘
变为 ‘0‘
,‘0‘
变为 ‘9‘
。每次旋转都只能旋转一个拨轮的一位数字。
锁的初始数字为 ‘0000‘
,一个代表四个拨轮的数字的字符串。
列表 deadends
包含了一组死亡数字,一旦拨轮的数字和列表里的任何一个元素相同,这个锁将会被永久锁定,无法再被旋转。
字符串 target
代表可以解锁的数字,你需要给出最小的旋转次数,如果无论如何不能解锁,返回 -1。
示例 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
提示:
死亡列表deadends
的长度范围为 [1,500]
。 目标数字 target
不会在 deadends
之中。 每个 deadends
和 target
中的字符串的数字会在 10,000 个可能的情况 ‘0000‘
到 ‘9999‘
中产生。 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 = 017 18 // Tip: Start from both sIDes19 while !start.isEmpty && !end.isEmpty {20 var temp: Set<String> = []21 22 if !start.intersection(end).isEmpty {23 return steps24 }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 += 136 37 (start,end) = (end,temp)38 (startToNow,endToNow) = (endToNow,startToNow.union(temp))39 }40 41 return -142 }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 = s50 t[i] = (s[i] + 1) % 1051 res.insert(t.reduce("",{ return $0 + String($1) }))52 t[i] = (s[i] - 1 + 10) % 1053 res.insert(t.reduce("",{ return $0 + String($1) }))54 }55 return res56 }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) % 10117 }118 119 func decrementDecimal() -> Int {120 return (self - 1 + 10) % 10121 }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 = 014 while !q.isEmpty {15 let size = q.size16 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 = node22 neighbor[i] = (digit + 1) % 1023 if !visited.contains(neighbor) {24 q.push(neighbor)25 visited.insert(neighbor)26 }27 neighbor = node28 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 += 137 }38 return -139 }40 }41 42 struct Queue<T> {43 var arr = [T]()44 var head = 045 46 mutating func push(_ val: T) {47 arr.append(val)48 }49 50 mutating func pop() -> T {51 let res = arr[head]52 head += 153 return res54 }55 56 var isEmpty: Bool {57 return head >= arr.count58 }59 60 var size: Int {61 return arr.count - head62 }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 = 015 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 List22 23 for i in 0 ..< current.count {24 var nextValue = current25 nextValue[i].next()26 27 if !seen.contains(nextValue) {28 tempQ.append(nextValue)29 seen.insert(nextValue)30 }31 32 var prevValue = current33 prevValue[i].prev()34 35 if !seen.contains(prevValue) {36 tempQ.append(prevValue)37 seen.insert(prevValue)38 }39 }40 }41 level += 142 q = tempQ43 44 }45 return -146 }47 }48 49 extension Int {50 mutating func next() {51 self = (self + 1) % 1052 }53 mutating func prev() {54 self = (self + 10 - 1) % 1055 }56 }
772ms
1 class Solution { 2 func openLock(_ deadends: [String],_ target: String) -> Int { 3 let target = Array(target).map{ Int("\(") })! 40 let deadends = Set(Array(deadends).map{ $".map{ Int(\(") } }) 5)!var() 6 visited = Set<[Int]>var0 0 queue = [([0,)]], 7var0 8 i = while queue.count { 9 i != queue[i]10 let (candIDate,index) =111 i += ifcontinue } visited.contains(candIDate) || deadends.contains(candIDate) { 12ifreturn index } candIDate == target { 13 visited.insert(candIDate)14 forin 0 j 3 {...15var candIDate 16 c =19 c[j] = (c[j] + 17) % 1)) queue.append((c,index+18 }19 forin 0 j 3 {...20var candIDate 21 c =09 c[j] = c[j] == 1 ? 22 : c[j] - 1)) queue.append((c,index+23 }24 if100000 return i > 10000 { } -25 }26 return1 27 - }28 1class }
784ms
Solution { 2 queue[i]10 func openLock(_ deadends: [String],index) =111 i += ifcontinue } visited.contains(candIDate) || deadends.contains(candIDate) { 12ifreturn index } candIDate == target { 13 visited.insert(candIDate)14 forin 0 j 3 {...15var candIDate 16 c =var c[j] 17 cj =19 c[j] = (cj + 18) % 1)) queue.append((c,index+1909 c[j] = cj == 1 ? 20 : cj - 1)) queue.append((c,index+21 }22 }23 return1 24 - }25 1class }Runtime: 864 ms Memory Usage: 20.3 MB
Solution { 2 Int { 3 func openLock(_ deadends: [String],_ target: String) ->var(deadends) 4 deadlock:Set<String> = Set<String>if" 0000 deadlock.contains(") 5 { 6 return1 7 - } 8 var0 9 res:Int = var" 0000 visited:Set<String> = ["]10var" 0000 q:[String] = ["]11whileq.isEmpty) 12(! {13 114 res += forin from k 0 strIDe(1:q.count,to:),by:-15 {16 q.removeFirst()17 let t:String = Array(t)18 let arrChar:[Character] =0.ascii} let arrInt:[Int] = arrChar.map{$19forin 0 i t.count 20..< {21 var arrChar[i] 22 c:Character =var arrInt[i] 23 num:Int =var0 " str1:String = t.subString(9,i) + String(c == "048 ? 1 : num - 1 + )) + t.subString(i + 24var0 " str2:String = t.subString(0,i) + String(c == "948 ? 1 : num - 1 - )) + t.subString(i + 25if target 26 str1 == target || str2 == {27 return res 28 }29 ifdeadlock.contains(str1) 30 !visited.contains(str1) && ! {31 q.append(str1)32 }33 ifdeadlock.contains(str2) 34 !visited.contains(str2) && ! {35 q.append(str2)36 }37 visited.insert(str1)38 visited.insert(str2) 39 } 40 }41 }42 return1 43 - }44 }45 46// Character扩展 47extension Character 48 { 49 //Character转ASCII整数值(定义小写为整数值) 50var ascii: Int { 51get { 52return0 ) Int(self.unicodeScalars.first?.value ?? 53 } 54 } 55 }56 57extension String { 58 // 截取字符串:指定索引和字符数 59// - begin: 开始截取处索引 60// - count: 截取的字符数量 61 String {62 func subString(_ begin:Int,_ count:Int) ->0,begin)) let start = self.index(self.startIndex,offsetBy: max(63 count))64 let end = self.index(self.startIndex,offsetBy: min(self.count,begin +returnend]) 65 String(self[start..< }66 67// 截取字符串:从index到结束处 68// - Parameter index: 开始索引 69// - Returns: 子字符串 70 String {71 func subString(_ index: Int) -> self.count)72 let theIndex = self.index(self.endindex,offsetBy: index -returnendindex]) 73 String(self[theIndex..< }74 }@H_419_2305@ 总结
以上是内存溢出为你收集整理的[Swift]LeetCode752. 打开转盘锁 | Open the Lock全部内容,希望文章能够帮你解决[Swift]LeetCode752. 打开转盘锁 | Open the Lock所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)