1
+ //你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
2
+ // 。每个拨轮可以自由旋转:例如把 '9' 变为 '0','0' 变为 '9' 。每次旋转都只能旋转一个拨轮的一位数字。
3
+ //
4
+ // 锁的初始数字为 '0000' ,一个代表四个拨轮的数字的字符串。
5
+ //
6
+ // 列表 deadends 包含了一组死亡数字,一旦拨轮的数字和列表里的任何一个元素相同,这个锁将会被永久锁定,无法再被旋转。
7
+ //
8
+ // 字符串 target 代表可以解锁的数字,你需要给出解锁需要的最小旋转次数,如果无论如何不能解锁,返回 -1 。
9
+ //
10
+ //
11
+ //
12
+ // 示例 1:
13
+ //
14
+ //
15
+ //输入:deadends = ["0201","0101","0102","1212","2002"], target = "0202"
16
+ //输出:6
17
+ //解释:
18
+ //可能的移动序列为 "0000" -> "1000" -> "1100" -> "1200" -> "1201" -> "1202" -> "0202"。
19
+ //注意 "0000" -> "0001" -> "0002" -> "0102" -> "0202" 这样的序列是不能解锁的,
20
+ //因为当拨动到 "0102" 时这个锁就会被锁定。
21
+ //
22
+ //
23
+ // 示例 2:
24
+ //
25
+ //
26
+ //输入: deadends = ["8888"], target = "0009"
27
+ //输出:1
28
+ //解释:
29
+ //把最后一位反向旋转一次即可 "0000" -> "0009"。
30
+ //
31
+ //
32
+ // 示例 3:
33
+ //
34
+ //
35
+ //输入: deadends = ["8887","8889","8878","8898","8788","8988","7888","9888"], targ
36
+ //et = "8888"
37
+ //输出:-1
38
+ //解释:
39
+ //无法旋转到目标数字且不被锁定。
40
+ //
41
+ //
42
+ // 示例 4:
43
+ //
44
+ //
45
+ //输入: deadends = ["0000"], target = "8888"
46
+ //输出:-1
47
+ //
48
+ //
49
+ //
50
+ //
51
+ // 提示:
52
+ //
53
+ //
54
+ // 1 <= deadends.length <= 500
55
+ // deadends[i].length == 4
56
+ // target.length == 4
57
+ // target 不在 deadends 之中
58
+ // target 和 deadends[i] 仅由若干位数字组成
59
+ //
60
+ // Related Topics 广度优先搜索 数组 哈希表 字符串
61
+ // 👍 360 👎 0
62
+
63
+
64
+ package com .jacobs .basic .leetcode .editor .cn ;
65
+
66
+ import java .util .HashSet ;
67
+ import java .util .LinkedList ;
68
+ import java .util .Queue ;
69
+ import java .util .Set ;
70
+
71
+ public class OpenTheLock {
72
+ public static void main (String [] args ) {
73
+ Solution solution = new OpenTheLock ().new Solution ();
74
+ System .out .println (solution .openLock (new String []{"0201" , "0101" , "0102" , "1212" , "2002" }, "0202" ));
75
+ }
76
+
77
+ //leetcode submit region begin(Prohibit modification and deletion)
78
+ class Solution {
79
+ public int openLock (String [] deadends , String target ) {
80
+ //使用bfs枚举所有可能性
81
+ Queue <String > queue = new LinkedList <>();
82
+ Set <String > deadSet = new HashSet <>();
83
+ for (int i = 0 ; i < deadends .length ; i ++) {
84
+ deadSet .add (deadends [i ]);
85
+ }
86
+ Set <String > visited = new HashSet <>();
87
+ queue .add ("0000" );
88
+ int step = 0 ;
89
+ while (!queue .isEmpty ()) {
90
+ int queueSize = queue .size ();
91
+ for (int i = 0 ; i < queueSize ; i ++) {
92
+ String str = queue .poll ();
93
+ // 需要记录当前的层,也即是最少的步数
94
+ if (deadSet .contains (str )) {
95
+ continue ;
96
+ }
97
+ if (str .equals (target )) {
98
+ return step ;
99
+ }
100
+
101
+ // 同一层总共有四种变法
102
+ for (int j = 0 ; j < 4 ; j ++) {
103
+ String plusStr = plusOne (str , j );
104
+ if (!visited .contains (plusStr )) {
105
+ visited .add (plusStr );
106
+ queue .add (plusStr );
107
+ }
108
+ String minusStr = minusOne (str , j );
109
+ if (!visited .contains (minusStr )) {
110
+ visited .add (minusStr );
111
+ queue .add (minusStr );
112
+ }
113
+ }
114
+ }
115
+ step ++;
116
+ }
117
+
118
+ return -1 ;
119
+ }
120
+
121
+ private String plusOne (String str , int i ) {
122
+ char [] chaArr = str .toCharArray ();
123
+ if (chaArr [i ] == '9' ) {
124
+ chaArr [i ] = '0' ;
125
+ } else {
126
+ chaArr [i ] += 1 ;
127
+ }
128
+
129
+ return new String (chaArr );
130
+ }
131
+
132
+ private String minusOne (String str , int i ) {
133
+ char [] chaArr = str .toCharArray ();
134
+ if (chaArr [i ] == '0' ) {
135
+ chaArr [i ] = '9' ;
136
+ } else {
137
+ chaArr [i ] -= 1 ;
138
+ }
139
+
140
+ return new String (chaArr );
141
+ }
142
+ }
143
+ //leetcode submit region end(Prohibit modification and deletion)
144
+
145
+ }
0 commit comments