-
Notifications
You must be signed in to change notification settings - Fork 225
/
1036-escape-a-large-maze.js
99 lines (94 loc) · 2.24 KB
/
1036-escape-a-large-maze.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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
/**
* @param {number[][]} blocked
* @param {number[]} source
* @param {number[]} target
* @return {boolean}
*/
const isEscapePossible = function(blocked, source, target) {
const blockedSet = new Set()
for (let el of blocked) {
let key = el[0] + "," + el[1]
blockedSet.add(key)
}
return canVisit(blockedSet, source, target) && canVisit(blockedSet, target, source)
}
function canVisit(blocked, start, end) {
const visited = new Set()
return dfs(blocked, start[0], start[1], end[0], end[1], visited)
}
function dfs(blocked, i, j, m, n, visited) {
visited.add(i + "," + j)
const dirs = [[i - 1, j], [i + 1, j], [i, j + 1], [i, j - 1]]
if ((i == m && j == n) || visited.size >= 20000) {
return true
}
for (let dir of dirs) {
let nextKey = dir[0] + "," + dir[1]
if (
dir[0] >= 0 &&
dir[1] >= 0 &&
dir[0] < 1e6 &&
dir[1] < 1e6 &&
!blocked.has(nextKey) &&
!visited.has(nextKey)
) {
if (dfs(blocked, dir[0], dir[1], m, n, visited)) {
return true
}
}
}
return false
}
// another
/**
* @param {number[][]} blocked
* @param {number[]} source
* @param {number[]} target
* @return {boolean}
*/
const isEscapePossible = function(blocked, source, target) {
if (blocked.length < 2) {
return true
}
// if (blocked[0][0] == 100025) {
// return false
// }
const blockSet = new Set(
blocked.map(el => {
return el[0] + "," + el[1]
})
)
let targetR, targetC, curR, curC
;[targetR, targetC] = target
let visited = new Set([])
let DIRS = [[0, 1], [-1, 0], [0, -1], [1, 0]],
queue = [source]
const inBound = (r, c) => {
return r >= 0 && c >= 0 && r < 1000000 && c < 1000000
}
let count = 0
while (queue.length > 0) {
count++
;[curR, curC] = queue.shift()
if (count > 20000) {
return true
}
for (let dir of DIRS) {
const newR = curR + dir[0],
newC = curC + dir[1]
if (
!inBound(newR, newC) ||
blockSet.has(newR + "," + newC) ||
visited.has(newR + "," + newC)
) {
continue
}
if (newR == targetR && newC == targetC) {
return true
}
visited.add(newR + "," + newC)
queue.push([newR, newC])
}
}
return false
}