-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
0752-open-the-lock.js
64 lines (58 loc) · 2.21 KB
/
0752-open-the-lock.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/**
* @param {string[]} deadends
* @param {string} target
* @return {number}
*/
var openLock = function(deadends, target) {
// General approach:
// Start at the end, mark that spot to be 0 away from target
// Find all the valid neighbors through bfs, mark those as 1
// Find all _their_ valid neighbors, mark those as ++ etc
// Until we find 0000. Whatever we mark that as is the number. BFS will guarantee it's the shortest path
let q = [target]; // our BFS Queue
let mem = {}; // to keep track what we already have visited
mem[target] = 0; // starting distance of the end
// Helper function that given a position, will generate all the numbers we
// can create in 1 move;
let getNextPositions = function (pos) {
// one above, one below
let dir = [-1, 1];
let arr = pos.split('');
let positions = [];
let i, j;
for (j = 0; j < 2; j++) {
let next = '';
// for each number in the position
for (i = 0; i < 4; i++) {
// logic is not just +1 -1, have to deal with wrapping around
let n = (10 + parseInt(arr[i], 10) + dir[j]) % 10;
// clone to not ruin our array for the next number
let next = [...arr];
// set our 1 change
next[i] = n;
positions.push(next.join(''));
}
}
return positions;
}
while (q.length) {
// dequeue a position to check out
let pos = q.shift();
// if it's 0000 we're done. BFS guarantees it's the shortest possible
if (pos === '0000') {
return mem[pos];
} else {
let next = getNextPositions(pos);
next.forEach(function(n) {
// if we haven't seen n before, and it's not a dead end,
if (mem[n] === undefined && !deadends.includes(n)) {
// mark the distance and enqueue to check out next
mem[n] = mem[pos] + 1;
q.push(n);
}
})
}
}
// if we end up here, we couldn't find it
return -1;
};