一:岛屿数量
假期结束了,没有足够时间刷题了,因此往后只采用一种语言解题,方法还是向官方看齐

1. 深度优先搜索
遍历所有元素,然后将该元素的周围为1的元素设为0,依次递归,直到下一次循环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class Solution { public: int row = 0; int col = 0; int numIslands(vector<vector<char>>& grid) { int num = 0; row = grid.size(); if (row == 0) return num; col = grid[0].size(); if (col == 0) return num; for (int i = 0; i < row; ++i) for (int j = 0; j < col; ++j) { if (grid[i][j] == '1') { ++num; recursion(grid, i, j); } } return num; } void recursion(vector<vector<char>>& grid, int i, int j) { grid[i][j] = 0; if (i - 1 >= 0 && grid[i - 1][j] == '1') recursion(grid, i - 1, j); if (j - 1 >= 0 && grid[i][j - 1] == '1') recursion(grid, i, j - 1); if (i + 1 < row && grid[i + 1][j] == '1') recursion(grid, i + 1, j); if (j + 1 < col && grid[i][j + 1] == '1') recursion(grid, i, j + 1); } };
|

2. 广度优先搜索
广度使用队列来维护节点,优先处理队列顶端的前后左右四个元素
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| class Solution { public: int row = 0; int col = 0; int numIslands(vector<vector<char>>& grid) { int num = 0; row = grid.size(); if (row == 0) return num; col = grid[0].size(); if (col == 0) return num; queue<pair<int, int>> queueNum; for (int i = 0; i < row; ++i) for (int j = 0; j < col; ++j) if (grid[i][j] == '1') { ++num; grid[i][j] = '0'; queueNum.push(pair(i, j)); while (!queueNum.empty()) { auto cur = queueNum.front(); queueNum.pop(); int i = cur.first; int j = cur.second; if (i - 1 >= 0 && grid[i - 1][j] == '1') { grid[i - 1][j] = '0'; queueNum.push(pair(i - 1, j)); } if (j - 1 >= 0 && grid[i][j - 1] == '1') { grid[i][j - 1] = '0'; queueNum.push(pair(i, j - 1)); } if (i + 1 < row && grid[i + 1][j] == '1') { grid[i + 1][j] = '0'; queueNum.push(pair(i + 1, j)); } if (j + 1 < col && grid[i][j + 1] == '1') { grid[i][j + 1] = '0'; queueNum.push(pair(i, j + 1)); } } } return num; } };
|

3. 并查集
这个数据结构就是为了处理这种“查询两个元素是否属于同一集合”和“合并两个元素所在的集合”的操作而生的。parent.push_back(i * n + j)将每个元素的父节点保存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| class UnionFind { public: vector<int> parent; vector<int> depth; int count = 0; UnionFind(vector<vector<char>>& grid) { int row = grid.size(); int col = grid[0].size(); for (int i = 0; i < row; ++i) for (int j = 0; j < col; ++j) { if (grid[i][j] == '1') { parent.emplace_back(i * col + j); ++count; } else parent.emplace_back(-1); depth.emplace_back(0); } } int Find(int i) { if (parent[i] != i) parent[i] = Find(parent[i]); return parent[i]; } void Unite(int x, int y) { x = Find(x); y = Find(y); if (x != y) { if (depth[x] < depth[y]) parent[x] = y; else if (depth[x] > depth[y]) parent[y] = x; else parent[x] = y; --count; x > y ? ++depth[y] : ++depth[x]; } } };
class Solution { public: int numIslands(vector<vector<char>>& grid) { int nr = grid.size(); if (!nr) return 0; int nc = grid[0].size(); UnionFind uf(grid); for (int r = 0; r < nr; ++r) for (int c = 0; c < nc; ++c) if (grid[r][c] == '1') { grid[r][c] = '0'; if (r - 1 >= 0 && grid[r-1][c] == '1') uf.Unite(r * nc + c, (r-1) * nc + c); if (r + 1 < nr && grid[r+1][c] == '1') uf.Unite(r * nc + c, (r+1) * nc + c); if (c - 1 >= 0 && grid[r][c-1] == '1') uf.Unite(r * nc + c, r * nc + c - 1); if (c + 1 < nc && grid[r][c+1] == '1') uf.Unite(r * nc + c, r * nc + c + 1); } return uf.count; } };
|

二:腐烂的橘子

1. 多源广度优先搜索
使用栈来维护每一层,然后依次判断该层每个节点的上下左右是否被感染,因为每分钟只能感染周围
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| class Solution { public: int orangesRotting(vector<vector<int>>& grid) { int time = 0; int numFre = 0; int row = grid.size(); int col = grid[0].size(); queue<pair<int, int>> Q; if (row == 0 || col == 0 ) return 0; for (int i = 0; i < row; ++i) for (int j = 0; j < col; ++j) { if (grid[i][j] == 2) Q.push(pair{i ,j}); if (grid[i][j] == 1) ++numFre; } if (numFre == 0) return 0; while (!Q.empty()) { int size = Q.size(); ++time; for (int i = 0; i < size; ++i) { int x = Q.front().first; int y = Q.front().second; Q.pop(); if (x - 1 >= 0 && grid[x - 1][y] == 1) { grid[x - 1][y] = 2; Q.push(pair{x - 1, y}); --numFre; } if (x + 1 < row && grid[x + 1][y] == 1) { grid[x + 1][y] = 2; Q.push(pair{x + 1, y}); --numFre; } if (y - 1 >= 0 && grid[x][y - 1] == 1) { grid[x][y - 1] = 2; Q.push(pair{x, y - 1}); --numFre; } if (y + 1 < col && grid[x][y + 1] == 1) { grid[x][y + 1] = 2; Q.push(pair{x, y + 1}); --numFre; } } } if (numFre != 0) return -1; return time - 1; } };
|

三:课程表

1. 深度优先搜索
实际上是判断该结构是否为有向无环图,使用0、1、2来表示节点的状态,再次遇到1表示存在环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| class Solution { public: vector<vector<int>> edge; vector<int> visit; bool canFinish(int numCourses, vector<vector<int>>& prerequisites) { edge.resize(numCourses); visit.resize(numCourses); for (auto& it : prerequisites) edge[it[1]].emplace_back(it[0]); for (int i = 0; i < numCourses; ++i) if (visit[i] == 0) { if (!recursion(i)) return false; } return true; } bool recursion(int i) { visit[i] = 1; for (auto sub : edge[i]) { if (visit[sub] == 0) { if (!recursion(sub)) return false; } else if(visit[sub] == 1) return false; } visit[i] = 2; return true; } };
|

2. 广度优先搜索
用队列维护没有入度的节点,然后对每个子节点的入度减一,然后添加子节点到队列,记录的子节点数量和题目要求的值相同表明可以完成课程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
| class Solution { public: bool canFinish(int numCourses, vector<vector<int>>& prerequisites) { vector<vector<int>> edge; vector<int> inEdge; edge.resize(numCourses); inEdge.resize(numCourses); for (auto& it : prerequisites) { edge[it[1]].emplace_back(it[0]); ++inEdge[it[0]]; } queue<int> q; int allNum = 0; for (int i = 0; i < numCourses; ++i) if (inEdge[i] == 0) q.push(i); while (!q.empty()) { ++allNum; int cur = q.front(); q.pop(); for (auto& sub : edge[cur]) { --inEdge[sub]; if (inEdge[sub] == 0) q.push(sub); } } return allNum == numCourses; } };
|
