dfs算法通常使用递归实现,逻辑清晰。在递归开头写一个跳出条件,然后继续向下递归遍历即可。要用一个额外的空间记录节点访问情况,遍历过的地方不再遍历,防止陷入循环,或者在原空间上进行修改。下面给出图上的dfs算法实现,与树有关的算法在树的博客中单独总结。
给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。
输入:
11110
11010
11000
00000
输出: 1
输入:
11000
11000
00100
00011
输出: 3
线性扫描整个二维网格,如果一个结点包含'1',则以其为根结点启动深度优先搜索。在深度优先搜索过程中,每个访问过的结点被标记为'0'。计数启动深度优先搜索的根结点的数量,即为岛屿的数量。在搜索时遇到超过边界或节点值为‘1’时终止搜索,否则向四个方向继续进行dfs。
class Solution {
public int numIslands(char[][] grid) {
int ret = 0;
for(int i=0;i=rowMax || col>=colMax || grid[row][col] == '0') {
return;
}
grid[row][col] = '0';
dfs(grid,row-1,col);
dfs(grid,row+1,col);
dfs(grid,row,col-1);
dfs(grid,row,col+1);
}
}
给定一个二维的矩阵,包含 'X' 和 'O'(字母 O)。
找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O' 用 'X' 填充。
示例:
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'。如果两个元素在水平或垂直方向相邻,则称它们是“相连”的。
在边界进行dfs,将‘O’替换为‘#’,可将边界相邻的全部替换为‘#’,最后遍历一遍矩阵,将‘O’替换为‘X’,将‘#’替换为‘O’。
class Solution {
public void solve(char[][] board) {
if (board.length == 0) {
return;
}
int rowMax = board.length;
int colMax = board[0].length;
for(int i=0;i=rowMax || col>=colMax || board[row][col]=='X'
|| board[row][col]=='#') {
return;
}
board[row][col] = '#';
dfs(board,row-1,col);
dfs(board,row+1,col);
dfs(board,row,col-1);
dfs(board,row,col+1);
}
}
给你无向连通图中一个节点的引用,请你返回该图的 深拷贝(克隆)。
class Node { public int val; public Listneighbors; }
使用哈希表存储克隆图中的节点,key为val,值为克隆图的Node,克隆当前节点后,对其邻居节点进行dfs克隆。
class Solution {
public Node cloneGraph(Node node) {
if(node == null) {
return null;
}
Map map = new HashMap<>();
Node root = new Node(node.val);
map.put(root.val,root);
dfs(map,node,root);
return root;
}
public void dfs(Map map,Node oldNode,Node newNode) {
for(Node node:oldNode.neighbors) {
if (!map.containsKey(node.val)) {
map.put(node.val,new Node(node.val));
dfs(map,node,map.get(node.val));
}
newNode.neighbors.add(map.get(node.val));
}
}
}
给定一个整数矩阵,找出最长递增路径的长度。
对于每个单元格,你可以往上,下,左,右四个方向移动。 你不能在对角线方向上移动或移动到边界外(即不允许环绕)。
输入: nums =
[
[9,9,4],
[6,6,8],
[2,1,1]
]
输出: 4
解释: 最长递增路径为 [1, 2, 6, 9]。
输入: nums =
[
[3,4,5],
[3,2,6],
[2,2,1]
]
输出: 4
解释: 最长递增路径是 [3, 4, 5, 6]。注意不允许在对角线方向上移动。
朴素的想法,从每一个点开始进行dfs,返回其中的最大值,但这种方法有很多重复计算,可能某次的路径为之前的子路径,使得算法运行超时。使用记忆化dfs的方法,定义cache矩阵,cache[i][j]记录位置(i,j)点开始的最长递增路径长度。这样也不用维护访问数组。当cache[i][j]已经被计算过,再次遍历到这直接返回即可。
class Solution {
public int longestIncreasingPath(int[][] matrix) {
if(matrix.length == 0) {
return 0;
}
int m = matrix.length;
int n = matrix[0].length;
int[][] cache = new int[m][n];
int ret = 0;
for(int i=0;i=matrix.length || j>=matrix[0].length) {
return 0;
}
if (cache[i][j] != 0) { //已经计算过的直接返回
return cache[i][j];
}
int ret = 0;
// 向更大的方向遍历
if(i-1>=0 && matrix[i-1][j] > matrix[i][j]) {
int cur = dfs(i-1,j,matrix,cache);
ret = Math.max(ret,cur);
}
if(i+1 matrix[i][j]) {
int cur = dfs(i+1,j,matrix,cache);
ret = Math.max(ret,cur);
}
if(j-1>=0 && matrix[i][j-1] > matrix[i][j]) {
int cur = dfs(i,j-1,matrix,cache);
ret = Math.max(ret,cur);
}
if(j+1 matrix[i][j]) {
int cur = dfs(i,j+1,matrix,cache);
ret = Math.max(ret,cur);
}
cache[i][j] = ret+1; //加上当前这个格子
return ret+1;
}
}
给定一个 m x n 的非负整数矩阵来表示一片大陆上各个单元格的高度。“太平洋”处于大陆的左边界和上边界,而“大西洋”处于大陆的右边界和下边界。
规定水流只能按照上、下、左、右四个方向流动,且只能从高到低或者在同等高度上流动。
请找出那些水流既可以流动到“太平洋”,又能流动到“大西洋”的陆地单元的坐标。
给定下面的 5x5 矩阵:
太平洋 ~ ~ ~ ~ ~
~ 1 2 2 3 (5) *
~ 3 2 3 (4) (4) *
~ 2 4 (5) 3 1 *
~ (6) (7) 1 4 5 *
~ (5) 1 1 2 4 *
* * * * * 大西洋
返回:
[[0, 4], [1, 3], [1, 4], [2, 2], [3, 0], [3, 1], [4, 0]] (上图中带括号的单元).
从海洋反向流回陆地,即向更高的地方流动。维护两个矩阵,分别表示可以被太平洋和大西洋流到的地方,最后返回两个海洋都能流动到的地点的坐标。
class Solution {
public List> pacificAtlantic(int[][] matrix) {
List> ret = new ArrayList<>();
if(matrix.length == 0){
return ret;
}
boolean[][] ocean1 = new boolean[matrix.length][matrix[0].length];
boolean[][] ocean2 = new boolean[matrix.length][matrix[0].length];
for(int i=0;i p = new ArrayList<>();
p.add(i);
p.add(j);
ret.add(p);
}
}
}
return ret;
}
public void dfs(int[][] matrix,int i,int j,boolean[][] ocean) {
// 流过的地方不再流
if(ocean[i][j]) {
return;
}
ocean[i][j] = true;
if(i-1>=0 && matrix[i-1][j] >= matrix[i][j]) {
dfs(matrix,i-1,j,ocean);
}
if(i+1= matrix[i][j]) {
dfs(matrix,i+1,j,ocean);
}
if(j-1>=0 && matrix[i][j-1] >= matrix[i][j]) {
dfs(matrix,i,j-1,ocean);
}
if(j+1= matrix[i][j]) {
dfs(matrix,i,j+1,ocean);
}
}
}