递归实现islandPerimeter遇栈溢出及类型错误,求解决方案
问题成因与修复方案
一、RangeError: Maximum call stack size exceeded(调用栈溢出)
成因
递归过程中没有限制重复访问同一陆地单元格,导致无限递归调用,最终超出JavaScript引擎的调用栈容量。比如每次递归都处理同一个grid[i][j] = 1的单元格,没有标记已访问状态,调用栈会持续累积直到触发上限。
修复方法
- 新增已访问标记:可以直接修改原矩阵,将访问过的陆地单元格从
1改为其他值(比如2),确保每个单元格只被递归处理一次;也可以单独维护一个和原矩阵同尺寸的布尔矩阵记录访问状态。 - 严格控制递归终止条件:当遇到水域或越界情况时立即返回,避免无效递归。
二、TypeError: Cannot read properties of undefined (reading '1')
成因
递归时未先判断坐标是否在矩阵的合法范围内,就直接访问grid[i][j]。比如当i < 0、i >= 总行数、j < 0或j >= 总列数时,grid[i]会是undefined,此时读取grid[i][j]就会抛出该错误。
修复方法
在递归函数的最开头,先检查坐标合法性:如果坐标越界,直接返回1(因为越界的边属于岛屿周长的一部分),再进行后续的单元格值判断。
修复后的示例代码
function islandPerimeter(grid) { const rows = grid.length; if (rows === 0) return 0; const cols = grid[0].length; function dfs(i, j) { // 先判断坐标是否越界,越界贡献1条周长边 if (i < 0 || i >= rows || j < 0 || j >= cols) { return 1; } // 遇到水域,贡献1条周长边 if (grid[i][j] === 0) { return 1; } // 已访问过的陆地,不重复计算 if (grid[i][j] === 2) { return 0; } // 标记当前陆地为已访问 grid[i][j] = 2; // 递归遍历四个方向,累加周长 return dfs(i-1, j) + dfs(i+1, j) + dfs(i, j-1) + dfs(i, j+1); } // 遍历网格找到第一个陆地,启动递归计算 for (let i = 0; i < rows; i++) { for (let j = 0; j < cols; j++) { if (grid[i][j] === 1) { return dfs(i, j); } } } return 0; }
代码关键点说明
- 用
2标记已访问的陆地,彻底避免重复递归,解决栈溢出问题。 - 优先判断坐标越界,确保访问
grid[i][j]时坐标始终合法,解决undefined读取错误。 - 越界和水域场景都返回1,因为这两种情况都对应岛屿的一条外围边,直接计入周长。
内容的提问来源于stack exchange,提问作者Gourav Singh Rawat
相关产品推荐
相关产品推荐

