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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章