java中多维数组dfs本质是将数组视为隐式图,每个位置为节点、相邻位置为邻边;需防越界、防重复访问,并依目标调整逻辑:1.递归模板含边界/状态检查、标记、四向递归;2.迭代法用栈模拟,以dx/dy数组控制方向;3.常见变体包括岛屿计数、最大面积、路径存在性及带状态搜索;4.需注意不规则数组列长、栈溢出风险与visited复用。

Java 中在多维数组中进行深度优先搜索(DFS)遍历,本质是把数组当作隐式图来处理:每个位置(如 grid[i][j])是一个节点,其上下左右(有时含对角线)相邻位置是它的邻接节点。关键在于避免重复访问、防止越界、明确搜索目标(如找连通区域、岛屿数量、路径是否存在等)。
下面分几个实用角度说明:
1. 基础模板:二维数组上的递归 DFS
适用于网格类问题(如岛屿、迷宫、洪水填充等)。核心三步:标记已访问 → 探索四个方向 → 递归深入。
public void dfs(int[][] grid, int i, int j, boolean[][] visited) {
// 边界检查 + 访问状态检查
if (i = grid.length || j = grid[0].length
|| visited[i][j] || grid[i][j] == 0) { // 假设 0 表示不可通行/非目标
return;
}
visited[i][j] = true; // 标记为已访问(或直接改 grid[i][j] = 0 实现“原地标记”)
// 四个方向:上、下、左、右
dfs(grid, i - 1, j, visited);
dfs(grid, i + 1, j, visited);
dfs(grid, i, j - 1, visited);
dfs(grid, i, j + 1, visited);
}
注意:
-
visited数组用于防止重复进入同一格子;也可用“染色法”原地修改(如将1改为2),节省空间; - 若网格含障碍(如
0是墙,1是陆地),条件中需排除障碍; - 若需统计连通块大小,可在进入时
count++,作为参数传递或用闭包变量。
2. 非递归实现:用栈模拟 DFS(避免栈溢出)
适合超大网格或深度受限场景。手动维护坐标栈,每次弹出一个点,压入其未访问邻居。
public void dfsIterative(int[][] grid, int startI, int startJ, boolean[][] visited) {
Stack<int> stack = new Stack();
stack.push(new int[]{startI, startJ});
int[] dx = {-1, 1, 0, 0};
int[] dy = {0, 0, -1, 1};
while (!stack.isEmpty()) {
int[] cur = stack.pop();
int i = cur[0], j = cur[1];
if (i = grid.length || j = grid[0].length
|| visited[i][j] || grid[i][j] == 0) {
continue;
}
visited[i][j] = true;
// 将四个邻居压栈(顺序影响遍历方向,但不影响连通性)
for (int k = 0; k <p>注意: </p>
<ul>
<li>
<code>continue</code> 替代 <code>return</code>,因栈中可能存有无效坐标; </li>
<li>压栈顺序决定“最后访问谁”——比如先压右再压下,实际会先处理下(LIFO); </li>
<li>不用担心重复压栈,靠 <code>visited</code> 在开头拦截。</li>
</ul>
<p><strong>3. 实际应用中的常见变体</strong> </p>
<ul>
<li>
<strong>岛屿数量(LeetCode 200)</strong>:外层遍历每个格子,遇到未访问的 <code>1</code> 就启动一次 DFS,计数器加一; </li>
<li>
<strong>最大岛屿面积</strong>:DFS 返回当前连通块大小,取全局最大值; </li>
<li>
<strong>判断是否存在路径(起点→终点)</strong>:DFS 中加入 <code>if (i == endI && j == endJ) return true;</code>,提前终止; </li>
<li>
<strong>带状态的 DFS(如带步数、钥匙、时间)</strong>:此时不能只用二维 <code>visited</code>,需升级为三维甚至四维(如 <code>visited[i][j][mask]</code>),表示在位置 <code>(i,j)</code> 持有钥匙集合 <code>mask</code> 是否来过。</li>
</ul>
<p><strong>4. 安全与效率提醒</strong> </p>
<ul>
<li>多维数组维度不一致时(如 <code>grid[i]</code> 长度不同),务必用 <code>grid[i].length</code> 而非 <code>grid[0].length</code> 判断列数; </li>
<li>递归 DFS 深度过大(如 10⁴×10⁴ 网格全连通)可能触发 <code>StackOverflowError</code>,此时必须改用栈迭代; </li>
<li>若允许多次查询(如动态更新网格后重搜),建议封装成类,复用 <code>visited</code> 数组或重置逻辑。</li>
</ul>
<p>不复杂但容易忽略。</p></int>Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











