Leetcode 200. Number of Islands

Given a 2d grid map of '1’s (land) and '0’s (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.

在這裏插入圖片描述

method 1 DFS

使用深度優先搜索,每次遞歸往四個方向繼續搜索遞歸,並且本題可以修改所給數組,從而避免使用visited數組標記已經訪問過的元素

void helper(vector<vector<char>>& grid, int i, int j){
	if (i == -1 || j == -1 || i == grid.size() || j == grid[i].size()) return;
	if (grid[i][j] == '0') return;

	grid[i][j] = '0';

	helper(grid, i + 1, j);
	helper(grid, i - 1, j);
	helper(grid, i, j + 1);
	helper(grid, i, j - 1);

	
}

int numIslands2(vector<vector<char>>& grid) {
	int nums = 0;
	for (int i = 0; i < grid.size(); i++)
	{
		for (int j = 0; j < grid[i].size(); j++)
		{
			if (grid[i][j] == '1'){
				nums++;
				helper(grid, i, j);
			}
		}
	}

	return nums;
}

method 2 union find

使用並查集,將所有島併到一起,當遍歷某個點的時候,如果其四個方向中有一個方向是島,那麼就將他們併到一起

並查集註意點:

  1. 並查集的核心在於並查集數組、find方法和union方法,使用並查集的時候,要考慮好什麼時候union,並且union時,要清楚誰作父結點,誰作子結點
  2. 並查集數組中存儲的都是父結點的索引值,而不是結點自身的值,所以要將所給數組和並查集數組之間對應起來,像本題直接使用數組索引的計算方法映射過去,像另外一道題Leetcode_128_LongestConsecutiveSequence,就要使用map映射值和並查集數組中的位置
  3. 本題提供了一個記錄並查集中有幾顆樹的方法:使用一個計數器,一開始遇到每一個結點,就加一,但union時就減一,最後的值即樹的個數
 vector<int> par;
int islands = 0;

int find(int x){
	if (par[x] == x) return x;
	par[x] = find(par[x]);
	return par[x];
}

void union_(int id1, int id2){
	int par1 = find(id1);
	int par2 = find(id2);
	if (par1 != par2){
		par[par2] = par1;
        islands--;
	}

}


int numIslands(vector<vector<char>>& grid) {
	if(grid.size() == 0) return 0;
    int m = grid.size(), n = grid[0].size();
	int dirc[] = { 0, 1, 0, -1, 0 };
    for(int i = 0; i < m; i++){
        for(int j = 0; j < n; j++){
            if(grid[i][j] == '1') {
                islands++;
                par.push_back(i*n+j);
            }else par.push_back(-1);
        }
    }

	for (int i = 0; i < grid.size(); i++){
		for (int j = 0; j < grid[i].size(); j++)
		{
			if (grid[i][j] == '1'){
				for (int k = 0; k < 4; k++)
				{
					int x = i + dirc[k], y = j + dirc[k + 1];
					if (x >= 0 && y >= 0 && x < m && y < n && grid[x][y] == '1'){
						union_(i*n + j, x*n + y);
					}
				}

			}
		}
	}
	return islands;
}

summary

  1. 修改原數組爲其他值,可節省訪問數組的空間使用
  2. 並查集總結點
  3. 在二維數組中,遍歷方向的簡便方法:
int dirc[] = { 0, 1, 0, -1, 0 };
for (int k = 0; k < 4; k++){
	int x = i + dirc[k], y = j + dirc[k + 1];
	if (x >= 0 && y >= 0 && x < m && y < n && grid[x][y] == '1'){
			union_(i*n + j, x*n + y);
	}
}
發佈了93 篇原創文章 · 獲贊 9 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章