lc200. 岛屿数量(MD)

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

示例 1:

输入:grid = [
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
]
输出:1

示例 2:

输入:grid = [
["1","1","0","0","0"],
["1","1","0","0","0"],
["0","0","1","0","0"],
["0","0","0","1","1"]
]
输出:3

提示:

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

深搜即可,碰到一个 ’1‘ 就开始深搜,岛屿数+1,直到搜不动了就说明走到边界。注意这里每搜完一个格子都要把这个格子的值改成 ’0‘ ,要不然就会无限循环,根本搜不到尽头的

class Solution {
private int row, col;

public int numIslands(char[][] grid) {
if (grid == null || grid.length == 0) {
return 0;
}
row = grid.length;
col = grid[0].length;
int res = 0;
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (grid[i][j] == '1') {
res++;
dfs(grid, i, j);
}
}
}
return res;
}

private void dfs(char[][] grid, int x, int y) {
grid[x][y] = '0';
if (x - 1 >= 0 && grid[x - 1][y] == '1') dfs(grid, x - 1, y);
if (x + 1 < row && grid[x + 1][y] == '1') dfs(grid, x + 1, y);
if (y - 1 >= 0 && grid[x][y - 1] == '1') dfs(grid, x, y - 1);
if (y + 1 < col && grid[x][y + 1] == '1') dfs(grid, x, y + 1);
}
}

lc130. 被包围的区域(MD)

给你一个 m x n 的矩阵 board ,由若干字符 'X''O' ,找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O''X' 填充。

示例 1:

img

输入:board = [["X","X","X","X"],["X","O","O","X"],["X","X","O","X"],["X","O","X","X"]]
输出:[["X","X","X","X"],["X","X","X","X"],["X","X","X","X"],["X","O","X","X"]]
解释:被围绕的区间不会存在于边界上,换句话说,任何边界上的 'O' 都不会被填充为 'X'。 任何不在边界上,或不与边界上的 'O' 相连的 'O' 最终都会被填充为 'X'。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。

示例 2:

输入:board = [["X"]]
输出:[["X"]]

提示:

  • m == board.length
  • n == board[i].length
  • 1 <= m, n <= 200
  • board[i][j]'X''O'

和上一题基本类似

先看样例:样例1中,贴近于边界的 ’O‘ 并没有被标记为 ’X‘;反之,完全没有靠近边界,被 ’X‘ 包围的三个 ’O’ 最后被标记为 ‘X’ 了。这给了我们一个思路:从边界位置开始深搜,如果搜到了一个 ‘O’,就做一个特殊标记(我给的标记是 ‘A’);最后再对整个矩阵的每个格子做是否有标记的判断即可

class Solution {
private int row, col;

public void solve(char[][] board) {
if (board == null || board.length == 0) {
return;
}
row = board.length;
col = board[0].length;
for (int i = 0; i < row; i++) {
dfs(board, i, 0);
dfs(board, i, col - 1);
}
for (int i = 1; i < col - 1; i++) {
dfs(board, 0, i);
dfs(board, row - 1, i);
}
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
if (board[i][j] == 'A') {
board[i][j] = 'O';
} else if (board[i][j] == 'O') {
board[i][j] = 'X';
}
}
}
}

private void dfs(char[][] board, int x, int y) {
if (x < 0 || x >= row || y < 0 || y >= col || board[x][y] != 'O') {
return;
}
board[x][y] = 'A';
dfs(board, x + 1, y);
dfs(board, x - 1, y);
dfs(board, x, y + 1);
dfs(board, x, y - 1);
}
}

lc133. 克隆图(MD)

给你无向 连通 图中一个节点的引用,请你返回该图的 深拷贝(克隆)。

图中的每个节点都包含它的值 valint) 和其邻居的列表(list[Node])。

class Node {
public int val;
public List<Node> neighbors;
}

测试用例格式:

简单起见,每个节点的值都和它的索引相同。例如,第一个节点值为 1(val = 1),第二个节点值为 2(val = 2),以此类推。该图在测试用例中使用邻接列表表示。

邻接列表 是用于表示有限图的无序列表的集合。每个列表都描述了图中节点的邻居集。

给定节点将始终是图中的第一个节点(值为 1)。你必须将 给定节点的拷贝 作为对克隆图的引用返回。

示例 1:

img

输入:adjList = [[2,4],[1,3],[2,4],[1,3]]
输出:[[2,4],[1,3],[2,4],[1,3]]
解释:
图中有 4 个节点。
节点 1 的值是 1,它有两个邻居:节点 2 和 4 。
节点 2 的值是 2,它有两个邻居:节点 1 和 3 。
节点 3 的值是 3,它有两个邻居:节点 2 和 4 。
节点 4 的值是 4,它有两个邻居:节点 1 和 3 。

示例 2:

img

输入:adjList = [[]]
输出:[[]]
解释:输入包含一个空列表。该图仅仅只有一个值为 1 的节点,它没有任何邻居。

示例 3:

输入:adjList = []
输出:[]
解释:这个图是空的,它不含任何节点。

提示:

  • 这张图中的节点数在 [0, 100] 之间。
  • 1 <= Node.val <= 100
  • 每个节点值 Node.val 都是唯一的,
  • 图中没有重复的边,也没有自环。
  • 图是连通图,你可以从给定节点访问到所有节点。

这道题看似复杂,实际上……额也没那么简单

我个人总结一下这道题的难点:

  1. 要怎么处理好克隆出来的新节点和老节点的关系;如果出现了重复遍历的情况,怎么处理
  2. 怎么把邻居列表也克隆出来,换言之,怎么让邻居列表中的节点同样地去克隆出自己的新节点

如果这道题是初见,且没有看过题解,那么看了样例非常容易晕头转向。假设在面试中,碰到这道题,你没有做过,你能在15分钟之内把它做出来吗?

这里给一个思路。对于难点1,我们考虑使用哈希表来存储老节点和新克隆节点;对于难点2,考虑使用搜索,当然是用dfs还是bfs随你的便,我个人是用的dfs,递归遍历节点

/*
// Definition for a Node.
class Node {
public int val;
public List<Node> neighbors;
public Node() {
val = 0;
neighbors = new ArrayList<Node>();
}
public Node(int _val) {
val = _val;
neighbors = new ArrayList<Node>();
}
public Node(int _val, ArrayList<Node> _neighbors) {
val = _val;
neighbors = _neighbors;
}
}
*/

class Solution {
private HashMap<Node, Node> vis = new HashMap<>();

public Node cloneGraph(Node node) {
if (node == null) {
return node;
}
if (vis.containsKey(node)) {
return vis.get(node);
}
Node cloneNode = new Node(node.val, new ArrayList<>());
vis.put(node, cloneNode);
for (Node neighbor : node.neighbors) {
cloneNode.neighbors.add(cloneGraph(neighbor));
}
return cloneNode;
}
}

虽然这道题也是中等难度,但我个人感觉这道题明显比前两题要难。不知道大家有没有这种感觉