-
Notifications
You must be signed in to change notification settings - Fork 890
/
Copy pathMinesweeper.swift
64 lines (51 loc) · 1.84 KB
/
Minesweeper.swift
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
/**
* Question Link: https://leetcode.com/problems/minesweeper/
* Primary idea: Classic Depth-first Search. Check current node and dfs all directions if mine count is 0, update the board accordingly.
*
* Time Complexity: O(mn), Space Complexity: O(mn)
*
*/
class Minesweeper {
private let dirs = [(0, 1), (0, -1), (1, 0), (-1, 0), (1, 1), (-1, 1), (1, -1), (-1, -1)]
func updateBoard(_ board: [[Character]], _ click: [Int]) -> [[Character]] {
let i = click[0], j = click[1]
var board = board
if board[i][j] == "M" {
board[i][j] = "X".first!
return board
}
let m = board.count, n = board[0].count
var isVisited = Array(repeating: Array(repeating: false, count: n), count: m)
dfs(&board, i, j, &isVisited)
return board
}
private func dfs(_ board: inout [[Character]], _ i: Int, _ j: Int, _ isVisited: inout [[Bool]]) {
guard isValid(i, j, board) && !isVisited[i][j] else {
return
}
isVisited[i][j] = true
if board[i][j] == "E" {
var count = 0
for dir in dirs {
let x = i + dir.0, y = j + dir.1
if isValid(x, y, board) {
if board[x][y] == "X" || board[x][y] == "M" {
count += 1
}
}
}
if count == 0 {
board[i][j] = "B".first!
for dir in dirs {
let x = i + dir.0, y = j + dir.1
dfs(&board, x, y, &isVisited)
}
} else {
board[i][j] = String(count).first!
}
}
}
private func isValid(_ i: Int, _ j: Int, _ board: [[Character]]) -> Bool {
return i >= 0 && i < board.count && j >= 0 && j < board[0].count
}
}