website/content.en/ChapterFour/0700~0799/0752.Open-the-Lock.md
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: 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
Constraints:
1 <= deadends.length <= 500deadends[i].length == 4target.length == 4deadends.target and deadends[i] consist of digits only.You have a combination lock with four circular wheels. Each wheel has 10 digits: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'. Each wheel can rotate freely: for example, '9' can become '0', and '0' can become '9'. Each rotation can only rotate one wheel by one digit. The initial number of the lock is '0000', a string representing the digits of the four wheels. The list deadends contains a set of dead-end numbers; once the digits on the wheels match any element in the list, the lock will be permanently locked and can no longer be rotated. The string target represents the number that can unlock the lock. You need to return the minimum number of rotations required to unlock it; if it cannot be unlocked no matter what, return -1.
package leetcode
func openLock(deadends []string, target string) int {
if target == "0000" {
return 0
}
targetNum, visited := strToInt(target), make([]bool, 10000)
visited[0] = true
for _, deadend := range deadends {
num := strToInt(deadend)
if num == 0 {
return -1
}
visited[num] = true
}
depth, curDepth, nextDepth := 0, []int16{0}, make([]int16, 0)
var nextNum int16
for len(curDepth) > 0 {
nextDepth = nextDepth[0:0]
for _, curNum := range curDepth {
for incrementer := int16(1000); incrementer > 0; incrementer /= 10 {
digit := (curNum / incrementer) % 10
if digit == 9 {
nextNum = curNum - 9*incrementer
} else {
nextNum = curNum + incrementer
}
if nextNum == targetNum {
return depth + 1
}
if !visited[nextNum] {
visited[nextNum] = true
nextDepth = append(nextDepth, nextNum)
}
if digit == 0 {
nextNum = curNum + 9*incrementer
} else {
nextNum = curNum - incrementer
}
if nextNum == targetNum {
return depth + 1
}
if !visited[nextNum] {
visited[nextNum] = true
nextDepth = append(nextDepth, nextNum)
}
}
}
curDepth, nextDepth = nextDepth, curDepth
depth++
}
return -1
}
func strToInt(str string) int16 {
return int16(str[0]-'0')*1000 + int16(str[1]-'0')*100 + int16(str[2]-'0')*10 + int16(str[3]-'0')
}