递归实现蛇形遍历矩阵遇栈溢出错误,寻求问题排查帮助
蛇形矩阵遍历函数栈溢出问题排查
问题描述
我尝试实现一个函数,接收n×n矩阵(数组的数组),返回按顺时针蛇形遍历后的一维数组。但该代码仅在3×3矩阵下运行正常,矩阵更大时会触发Maximum call stack size exceeded错误。原代码如下:
function snail (array) { let result = [] function resultFilling(arrayForResult) { if (arrayForResult[0].length === 1) { result.push(arrayForResult[0][0]) return } for (let i = 0; i < arrayForResult.length - 1; i++) { result.push(arrayForResult[0][i]) } for (let i = 0; i < arrayForResult.length - 1; i++) { result.push(arrayForResult[i][arrayForResult.length - 1]) } for (let i = arrayForResult.length - 1; i > 0; i--) { result.push(arrayForResult[arrayForResult.length - 1][i]) } for (let i = arrayForResult.length - 1; i > 0; i--) { result.push(arrayForResult[i][0]) } let newArr = array.reduce((accum, item, index) => { if (index > 0 && index < array.length - 1) { accum.push(item.splice(1, item.length - 2)) } return accum }, []) if (newArr.length > 0) resultFilling(newArr) } resultFilling(array) return result }
错误原因分析
- 递归依赖原数组而非当前处理数组:构建
newArr时用了外层的array变量,而非当前递归接收的arrayForResult。这会导致每次递归生成的子矩阵完全错误,无法正确缩小问题规模,最终触发无限递归,栈溢出。 - 修改原数组导致数据破坏:使用
splice方法会直接修改原数组的元素,后续递归处理时的数组已经被篡改,逻辑混乱,进一步加剧递归异常。 - 边界条件缺失:仅判断了子数组长度为1的情况,没有处理矩阵为空、子数组为空等极端场景,可能导致不必要的递归调用。
修复后的代码
function snail(array) { const result = []; function resultFilling(currentArr) { // 边界判断:当前数组为空或子数组为空时直接返回 if (!currentArr.length || !currentArr[0].length) return; // 处理只剩单个元素的情况 if (currentArr.length === 1 && currentArr[0].length === 1) { result.push(currentArr[0][0]); return; } // 遍历顶部行(除最后一个元素) for (let i = 0; i < currentArr[0].length - 1; i++) { result.push(currentArr[0][i]); } // 遍历右侧列(除最后一个元素) for (let i = 0; i < currentArr.length - 1; i++) { result.push(currentArr[i][currentArr[0].length - 1]); } // 遍历底部行(反向,除第一个元素) for (let i = currentArr[currentArr.length - 1].length - 1; i > 0; i--) { result.push(currentArr[currentArr.length - 1][i]); } // 遍历左侧列(反向,除第一个元素) for (let i = currentArr.length - 1; i > 0; i--) { result.push(currentArr[i][0]); } // 生成新的子矩阵:取中间行,每行取中间部分(用slice不修改原数组) const newArr = currentArr.slice(1, -1).map(row => row.slice(1, -1)); if (newArr.length > 0) resultFilling(newArr); } resultFilling(array); return result; }
修改说明
- 将
newArr的构建逻辑改为基于currentArr(当前递归的数组),使用slice方法截取中间行和每行的中间部分,避免修改原数组。 - 完善边界判断,提前终止无效递归。
- 统一使用
currentArr[0].length来获取列数,适配可能的非方阵(虽然题目要求n×n,但增强鲁棒性)。
内容的提问来源于stack exchange,提问作者skusov
相关产品推荐
相关产品推荐

