130.被围绕的区域

100 阅读1分钟

题目:
给你一个 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)
}