题目:
给你一个 m x n 的矩阵 board ,由若干字符 'X' 和 'O' ,找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O' 用 'X' 填充。
算法:
方法一:dfs
先从四个边界开始访问,访问到x,标记为已访问(使用一个二维数组标记),访问到o且没有访问过,dfs标记已访问。这样所有被包围的o都是没有访问过的。
访问[1,n-2]行,[1,m-2]列,将所有没访问到的o标记为x
func solve(board [][]byte) {
dicts := [][]int{[]int{1, 0},[]int{0, 1},[]int{-1, 0},[]int{0, -1}}
n := len(board)
m := len(board[0])
visited := make([][]int, n)
for i := range visited {
visited[i] = make([]int, m)
}
var dfs func(i, j int)
dfs = func(i, j int) {
if i < 0 || i >= n || j < 0 || j >= m || visited[i][j] == 1 {
return
}
visited[i][j] = 1
if board[i][j] == byte('O') {
for k := range dicts {
x := i + dicts[k][0]
y := j + dicts[k][1]
dfs(x, y)
}
}
}
for i := 0; i < n; i ++ {
for j := 0; j < m; j ++ {
if i == 0 || j == 0 || i == n - 1 || j == m - 1 {
dfs(i, j)
}
}
}
// fmt.Println(visited)
for i := 1; i < n - 1; i ++ {
for j := 1; j < m - 1; j ++ {
if board[i][j] == byte('O') && visited[i][j] != 1 {
board[i][j] = byte('X')
}
}
}
}
方法二:并查集
思路:我们可以将边界上值为“O”的节点的父节点统一设置为一个dummyNode。然后遍历数组,如果某个坐标的值为“O”父节点不为dummyNode,则可以修改为“X",如果坐标的值为“O”父节点为dummyNode则和边界联通,不需要修改。
var unifind []int
func solve(board [][]byte) {
n := len(board)
m := len(board[0])
unifind = make([]int, m * n + 1)
var node func(i, j int) int
// 0-2, 0-2 3*3
node = func(i, j int) int {
return i * m + j
}
for i := range unifind {
unifind[i] = i
}
dummyNode := n * m
for i := 0; i < n; i ++ {
for j := 0; j < m; j ++ {
if board[i][j] == byte('O') {
if i == 0 || i == n - 1 || j == 0 || j == m - 1 {
merge(node(i, j), dummyNode)
} else {
if i > 0 && board[i - 1][j] == byte('O') {
merge(node(i, j), node(i - 1, j))
}
if i < n - 1 && board[i + 1][j] == byte('O') {
merge(node(i, j),node(i + 1, j))
}
if j > 0 && board[i][j - 1] == byte('O') {
merge(node(i, j),node(i, j - 1))
}
if j < m - 1 && board[i][j + 1] == byte('O') {
merge(node(i, j),node(i, j + 1))
}
}
}
}
}
for i := 0; i < n; i ++ {
for j := 0; j < m; j ++ {
if isConnect(node(i, j ), dummyNode) {
board[i][j] = byte('O')
} else {
board[i][j] = byte('X')
}
}
}
}
func find(x int) int {
if x == unifind[x] {
return x
}
father := find(unifind[x])
unifind[x] = father
return father
}
func merge(x, y int) {
xf := find(x)
yf := find(y)
if xf != yf {
unifind[xf] = yf
}
}
func isConnect(x, y int) bool {
return find(x) == find(y)
}