Leetcode 130. Surrounded Regions

Given a 2D board containing ‘X’ and ‘O’ (the letter O), capture all regions surrounded by ‘X’.

A region is captured by flipping all 'O’s into 'X’s in that surrounded region.
在这里插入图片描述
Explanation:

Surrounded regions shouldn’t be on the border, which means that any ‘O’ on the border of the board are not flipped to ‘X’. Any ‘O’ that is not on the border and it is not connected to an ‘O’ on the border will be flipped to ‘X’. Two cells are connected if they are adjacent cells connected horizontally or vertically.

method 1 DFS

深度优先遍历,将每一个和边界O联系的点都先设为E,最后再将O设置为X,将E设置回O

void helper_(vector<vector<char>>& board, int i, int j){
	if (board[i][j] == 'X' || board[i][j] == 'E') return;
	int dirc[] = { 0, 1, 0, -1, 0 };
	board[i][j] = 'E';
	int m = board.size(), n = board[i].size();
	for (int k = 0; k < 4; k++){
		int x = i + dirc[k];
		int y = j + dirc[k + 1];
		if (x < 0 || y < 0 || x == m || y == n || board[x][y] == 'X' || board[x][y] == 'E')
			continue;
		helper_(board, x, y);
	}
}

void solve2(vector<vector<char>>& board) {
	if (board.size() == 0) return;

	int m = board.size(), n = board[0].size();
	for (int i = 0; i < board.size(); i++){
		for (int j = 0; j < board[i].size(); j++){
			if (i == 0 || j == 0 || i == m - 1 || j == n - 1){
				if (board[i][j] == 'O')
					helper_(board, i, j);
			}
		}
	}

	for (int i = 0; i < board.size(); i++){
		for (int j = 0; j < board[i].size(); j++){
			if (board[i][j] == 'O') board[i][j] = 'X';
			else if (board[i][j] == 'E') board[i][j] = 'O';
		}
	}
}

method 2 union find

在做本题一直卡着的点:
重点1: unite,要知道是把谁union到谁
重点2: 要把四周往新结点 union。向上和向左代表之前的结点,如果之前结点的根为dummyNode,那么本结点也要,如果之前的结点的根并非dummyNode,那么要把之前的结点往新结点union,因为之后该新结点可能会union更新的结点
重点3: 因为边界的特殊性,所以不能再从4个方向union,这样会影响边界原本正确的根节点,所以只能从上,从左两个方向,这样就不会反复union

vector<int> pa;

int find(int n) {
	return pa[n] == n ? n : pa[n] = find(pa[n]);
}

void unite(int n1, int n2) {
	int p1 = find(n1);
    int p2 = find(n2);
    if (p1 == pa.size()-1) {
        pa[p2] = p1;
    } else {
        pa[p1] = p2;
    }
}

void solve(vector<vector<char>>& board) {
	if (board.empty() || board[0].empty()) {
		return;
	}
	int rows = board.size(), cols = board[0].size();
	pa.resize(rows * cols + 1);
	for (int i = 0; i < pa.size(); ++i) {
		pa[i] = i;
	}

	int dummyNode = pa.size()-1;
	for (int i = 0; i < rows; i++) {
		for (int j = 0; j < cols; j++) {
			if (board[i][j] == 'X') {
				continue;
			}

			if (i == 0 || j == 0 || i == rows-1 || j == cols - 1) {
				unite(dummyNode, i * cols + j);
			}
			if (i > 0 && board[i-1][j] == 'O') {
				unite((i - 1) * cols + j, i * cols + j);
			}
			if (j > 0 && board[i][j-1] == 'O') {
				unite( i * cols + j-1, i * cols + j);
			}
		}
	}

	for (int i = 0; i < rows; i++){
		for (int j = 0; j < cols; j++){
			if (board[i][j] == 'O' && find(i * cols + j) != dummyNode) 
                board[i][j] = 'X';
		}
	}
	
}

summary

  1. 将数组中不能改变的元素设置为其他值,最后再改回来,这样就避免了访问数组的使用,但要小心当改变元素的值会对周围元素是否改变值产生影响时,要慎重,如leetcode 73. Set Matrix Zeroes、Leetcode 289. Game of Life

  2. 引入dummyNode指向特殊节点!

  3. 注意遍历的方向,有时并不是要往四个方向都搜索,如在本题四个方向都搜索会造成重复union,最后导致错误

发布了93 篇原创文章 · 获赞 9 · 访问量 2万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章