You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:JS实现Snail算法遇TypeError,无法处理大尺寸二维数组

Snail算法遍历数组问题排查与修复

问题描述

正在解决名为Snail的算法任务:给定n×n数组,返回从最外层到中间顺时针遍历的元素。编写的JavaScript函数在结果数组长度≤3时可正常返回[1,2,3,4],但处理更大数组时报错:Uncaught TypeError: Cannot read properties of undefined (reading '2'),down函数能获取到元素4,但无法访问5及之后的元素。

原代码:

function snail(array){
  let arr=[...array] //copy of a passed array
  let result=[] //here function will add next blocks
  const y=arr.length; const x=arr[0].length //this is to measure size to stop while
  let cY=0,cX=0;//current Y axis and current X axis
  /*For the purpose of this function both axes start as 0(top left corner) and when going down is +1 instead of -1 as normally in math*/

    
    while(result.length<=x*y){//this should go throw all of the blocks
    result.push(...arr[cY].splice(cX,1,null))//take block and replace it with null
    right()//search for a block - by default starts from right function
    }
    
    
    function right(){//goes right(next index of current array)
    if(arr[cY][cX+1])
    {cX+=1}
    else{down()}
    }
    
    function down(){//goes down(next array of current index)
    if(arr[cY+1][cX])
    {cY++}
    else{left()}
    }
    
    function left(){//goes left(previous index of current array)
    if(arr[cY][cX-1])
    {cX--}
    else{up()}
    }
    
    function up(){//goes up(previous array of current index)
    if(arr[cY-1][cX])
    {cY--}
    else{right()}
    }
    
    return result
    }


console.log(snail([ [1,2,3],[8,9,4],[7,6,5]]))

错误原因分析

  1. 数组越界访问:当cY+1超过数组长度时,arr[cY+1]会变为undefined,此时访问arr[cY+1][cX]直接触发类型错误。比如3×3数组遍历到元素4后,后续尝试向下时cY+1=3,arr[3]不存在,访问其下标必然报错。
  2. 终止条件错误:while(result.length<=x*y)会导致循环多执行一次,当结果数组已收集完所有元素时,仍会尝试访问已处理的数组元素,引发错误。
  3. 元素判断逻辑缺陷:if(arr[cY][cX+1])会把值为0或null的元素误判为“不存在”(二者在JS中为假值),导致方向切换逻辑混乱,无法正确定位下一个元素。

修复方案

  1. 修正循环终止条件:改为while(result.length < x*y),确保收集完所有元素后立即停止循环。
  2. 安全边界检查:访问元素前先检查行/列是否在数组范围内,再判断元素是否未被标记为null。
  3. 优化元素标记与判断:直接赋值null标记已访问元素,判断时明确检查元素是否为null,避免假值干扰。

修复后的完整代码

function snail(array) {
  // 深拷贝二维数组,避免修改原输入
  let arr = array.map(row => [...row]);
  let result = [];
  const totalElements = arr.length * arr[0].length;
  let cY = 0, cX = 0;

  while (result.length < totalElements) {
    // 收集当前元素并标记为已访问
    result.push(arr[cY][cX]);
    arr[cY][cX] = null;

    // 按顺时针方向依次尝试切换
    if (cX + 1 < arr[cY].length && arr[cY][cX + 1] !== null) {
      cX++;
    } else if (cY + 1 < arr.length && arr[cY + 1][cX] !== null) {
      cY++;
    } else if (cX - 1 >= 0 && arr[cY][cX - 1] !== null) {
      cX--;
    } else if (cY - 1 >= 0 && arr[cY - 1][cX] !== null) {
      cY--;
    }
  }

  return result;
}

console.log(snail([[1,2,3],[8,9,4],[7,6,5]])); // 输出 [1,2,3,4,5,6,7,8,9]

额外优化方案(更简洁的方向管理)

用数组存储顺时针方向,通过索引切换方向,代码可读性与维护性更强:

function snail(array) {
  if (!array.length || !array[0].length) return [];
  const arr = array.map(row => [...row]);
  const result = [];
  // 定义顺时针方向:右、下、左、上
  const directions = [[0, 1], [1, 0], [0, -1], [-1, 0]];
  let dirIndex = 0;
  let y = 0, x = 0;
  const total = arr.length * arr[0].length;

  for (let i = 0; i < total; i++) {
    result.push(arr[y][x]);
    arr[y][x] = null;
    // 计算下一个位置
    let nextY = y + directions[dirIndex][0];
    let nextX = x + directions[dirIndex][1];
    // 检查下一个位置是否合法(在范围内且未被访问)
    if (nextY < 0 || nextY >= arr.length || nextX < 0 || nextX >= arr[0].length || arr[nextY][nextX] === null) {
      // 切换到下一个方向
      dirIndex = (dirIndex + 1) % 4;
      nextY = y + directions[dirIndex][0];
      nextX = x + directions[dirIndex][1];
    }
    y = nextY;
    x = nextX;
  }

  return result;
}

内容的提问来源于stack exchange,提问作者Kuba Nowoszyński

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 20:51:13