ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

1020. 飞地的数量(BFS 和并查集)

2022-05-22 16:03:50  阅读:166  来源: 互联网

标签:陆地 1020 int 查集 BFS grid visited col row


1020. 飞地的数量

给你一个大小为 m x n 的二进制矩阵 grid ,其中 0 表示一个海洋单元格、1 表示一个陆地单元格。

一次 移动 是指从一个陆地单元格走到另一个相邻(上、下、左、右)的陆地单元格或跨过 grid 的边界。

返回网格中 无法 在任意次数的移动中离开网格边界的陆地单元格的数量。

 

示例 1:

输入:grid = [[0,0,0,0],[1,0,1,0],[0,1,1,0],[0,0,0,0]]
输出:3
解释:有三个 1 被 0 包围。一个 1 没有被包围,因为它在边界上。

示例 2:

输入:grid = [[0,1,1,0],[0,0,1,0],[0,0,1,0],[0,0,0,0]]
输出:0
解释:所有 1 都在边界上或可以到达边界。

 

提示:

  • m == grid.length
  • n == grid[i].length
  • 1 <= m, n <= 500
  • grid[i][j] 的值为 0 或 1

方法一:(BFS)

 1 class Solution {
 2 public:
 3     bool isInArea(int x, int y) {
 4         return (x >= 0 && x < row && y >= 0 && y < col);
 5     }
 6     void addBoundryLandToQueue(const vector<vector<int>> &grid, queue<std::pair<int, int>> &q, vector<vector<bool>> &visited) {
 7         // 左右边界的陆地入队
 8         for (int i = 0; i < row; i++) {
 9             // 左边界陆地入队
10             if (grid[i][0] == 1) {
11                 q.push(make_pair(i, 0));
12                 visited[i][0] = true;
13             }
14             // 右边界陆地入队
15             if (grid[i][col - 1] == 1) {
16                 q.push(make_pair(i, col - 1));
17                 visited[i][col - 1] = true;
18             }
19         }
20         // 上下边界的陆地入队
21         for (int j = 1; j < col - 1; j++) {
22             // 上边界陆地入队
23             if (grid[0][j] == 1) {
24                 q.push(make_pair(0, j));
25                 visited[0][j] = true;
26             }
27             // 下边界陆地入队
28             if (grid[row - 1][j] == 1) {
29                 q.push(make_pair(row - 1, j));
30                 visited[row - 1][j] = true;
31             }
32         }
33     }
34     void bfsUpdateNeighborLandVisited(const vector<vector<int>> &grid, queue<std::pair<int,int>> &q, vector<vector<bool>> &visited) {
35         while (!q.empty()) {
36             int curX = q.front().first;
37             int curY = q.front().second;
38             q.pop();
39             for (auto &direction : g_direction) {
40                 int nextX = curX + direction[0];
41                 int nextY = curY + direction[1];
42                 /*
43                 * 1、不在矩阵范围内的跳过
44                 * 2、海洋方格跳过
45                 * 3、已访问的跳过
46                 */
47                 if (!isInArea(nextX, nextY) || grid[nextX][nextY] == 0 || visited[nextX][nextY]) {
48                     continue;
49                 }
50                 q.push(make_pair(nextX, nextY)); // 相邻陆地入队
51                 visited[nextX][nextY] = true; // 设置相邻陆地已访问
52             }
53         }
54     }
55     int getUnreachedLand(const vector<vector<int>> &grid, const vector<vector<bool>> &visited) {
56         int cnt = 0;
57         for (int i = 0; i < row; i++) {
58             for (int j = 0; j < col; j++) {
59                 if (grid[i][j] == 1 && !visited[i][j]) {
60                     cnt++;
61                 }
62             }
63         }
64         return cnt;
65     }
66     int numEnclaves(vector<vector<int>>& grid) {
67         row = grid.size();
68         col = grid[0].size();
69         vector<vector<bool>> visited(row, vector<bool>(col, false));
70         queue<std::pair<int, int>> q;
71         // 1、将边界陆地入队并设置已访问
72         addBoundryLandToQueue(grid, q, visited);
73         // 2、BFS矩阵刷新与边界相连的陆地并设置已访问
74         bfsUpdateNeighborLandVisited(grid, q, visited);
75         // 3、遍历方格统计未访问陆地数,即为无论怎么移动都不能离开边界的陆地单元格数量
76         return getUnreachedLand(grid, visited);
77     }
78 private:
79     int row;
80     int col;
81     // 顺时针上、右、下、左四个方向
82     vector<vector<int>> g_direction = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
83 };

方法二:(并查集)

 1 class UnionFindSet {
 2 public:
 3     void init(int n) {
 4         parent.resize(n);
 5         for (int i = 0 ; i < n; i++) {
 6             parent[i] = i;
 7         }
 8     }
 9     int findRoot(int x) {
10         if (x != parent[x]) {
11             parent[x] = findRoot(parent[x]);
12         }
13         return parent[x];
14     }
15     bool isConnected(int x, int y) {
16         return (findRoot(x) == findRoot(y));
17     }
18     void unify(int x, int y) {
19         if (isConnected(x, y)) {
20             return;
21         }
22         int xRoot = findRoot(x);
23         int yRoot = findRoot(y);
24         parent[xRoot] = yRoot;
25         return;
26     }
27 private:
28     vector<int> parent;
29 };
30 
31 class Solution : public UnionFindSet {
32 public:
33     bool isInArea(int x, int y) {
34         return (x >= 0 && x < row && y >= 0 && y < col);
35     }
36     int numEnclaves(vector<vector<int>>& grid) {
37         row = grid.size();
38         col = grid[0].size();
39         int n = row * col + 10; // 二维数组转换为一维,多分点内存防止越界访问
40         // 1、初始化并查集
41         init(n);
42         // 2、虚拟一个节点作为树的根节点row * col,将边界陆地与之相连
43         // 左、右边界陆地与虚拟根节点相连
44         for (int i = 0; i < row; i++) {
45             if (grid[i][0] == 1) {
46                 // 转换为一维坐标:i * col + 0与虚拟根节点row * col相连
47                 unify(i * col, row * col);
48             }
49             if (grid[i][col - 1] == 1) {
50                 // 转换为一维坐标:i * col + col - 1与虚拟根节点row * col相连
51                 unify(i * col + col - 1, row * col); 
52             }
53         }
54         // 上、下边界陆地与虚拟节点相连
55         for (int j = 0; j < col; j++) {
56             if (grid[0][j] == 1) {
57                 // 转换为一维坐标:0 * col + j与虚拟根节点row * col相连
58                 unify(j, row * col);
59             }
60             if (grid[row - 1][j] == 1) {
61                 // 转换为一维坐标:(row - 1) * col + j与虚拟根节点row * col相连
62                 unify((row - 1) * col + j, row * col);
63             }
64         }
65         // 3、遍历矩阵方格,将陆地相连
66         for (int i = 0; i < row; i++) {
67             for (int j = 0; j < col; j++) {
68                 if (grid[i][j] == 0) {
69                     continue;
70                 }
71                 for (auto &direction : g_direction) {
72                     int nextX = i + direction[0];
73                     int nextY = j + direction[1];
74                     if (!isInArea(nextX, nextY) || grid[nextX][nextY] == 0) {
75                         continue;
76                     }
77                     unify(nextX * col + nextY, i * col + j);
78                 }
79             }
80         }
81         // 4、遍历矩阵非边界方格,统计未与虚拟根节点相连的陆地,即为即为无论怎么移动都不能离开边界的陆地单元格数量
82         int cnt = 0;
83         for (int i = 1; i < row - 1; i++) {
84             for (int j = 1; j < col - 1; j++) {
85                 if (grid[i][j] == 1 && !isConnected(i * col + j, row * col)) {
86                     cnt++;
87                 }
88             }
89         }
90         return cnt;
91     }
92 private:
93     int row;
94     int col;
95     // 顺时针上、右、下、左四个方向
96     vector<vector<int>> g_direction = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
97 };

标签:陆地,1020,int,查集,BFS,grid,visited,col,row
来源: https://www.cnblogs.com/MGFangel/p/16298052.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有