
本文详解初学者在实现 findFirstMove 函数时因错误理解 splice() 行为而导致测试失败的根本原因,并提供清晰、健壮、符合基础语法要求的解决方案。
本文详解初学者在实现 `findfirstmove` 函数时因错误理解 `splice()` 行为而导致测试失败的根本原因,并提供清晰、健壮、符合基础语法要求的解决方案。
在 JavaScript 中查找二维数组中某个元素首次出现的位置,本质是遍历外层数组(行),再逐个检查内层数组(列),一旦匹配就立即返回 [rowIndex, colIndex]。这是一个典型的“早停遍历”问题——找到第一个即终止,无需收集所有结果。
你最初的代码逻辑存在两个关键误解:
过度收集 + 错误截取:使用双层循环将所有匹配位置(如
"a"出现多次)都push到newArr,再试图用splice(newArr.length - 2, 2)“取出最后两个”作为答案。这隐含假设目标元素至少出现两次,且你总想取“最后一次”的坐标——但题目明确要求第一次出现的索引。-
splice()的副作用被忽略:Array.prototype.splice()不仅返回被删除的元素,还会直接修改原数组。例如:let arr = [0, 0, 2, 1]; let removed = arr.splice(2, 2); // 删除索引2开始的2个元素 console.log(removed); // [2, 1] console.log(arr); // [0, 0] ← 原数组已被破坏!
在你的代码中,
newArr.splice(...)后返回的是被删掉的子数组(即test),但你却return newArr——此时newArr已被清空或截断,导致单次匹配时返回空数组[],而非预期的[0, 0]。
✅ 正确解法应遵循“发现即返回”原则,无需额外数组存储:
function findFirstMove(moves, char) {
for (let i = 0; i <p>这个版本:</p>
- 时间最优:最坏情况 O(m×n),但平均远优于收集全部再处理;
-
语义清晰:
return [i, j]直观表达“坐标对”,无歧义; - 零副作用:不创建冗余数组,不修改任何输入;
-
完全兼容基础语法:仅用
for循环、===、return和数组索引——正是 Rithm School 当前阶段所授内容。
⚠️ 注意事项:
- 不要试图用
splice、slice或其他数组方法“提取结果”,它们适用于已有数据的变换,而本题是搜索与定位; -
splice()的核心用途是原地增删数组元素(如删除某项、插入新项),不是“取子数组”的工具(该用slice()); - 测试失败往往源于逻辑与题意偏差,而非环境差异——你的 Chrome 控制台结果“看似正确”,实则是因测试数据中
"a"出现了两次(["a","b","c"]和["d","a","f"]),恰好让错误逻辑“碰巧”输出了[0,0];而 Rithm 的测试用例中"a"仅在[0][0]出现一次,暴露了splice清空数组的问题。
总结:编程初学阶段,优先追求逻辑准确和意图直译。遇到“找第一个”,就用 return 终止;遇到“没找到”,就统一 return -1。复杂操作(如收集、过滤、映射)应在掌握基础控制流后再引入。这不仅是解题技巧,更是构建可靠代码思维的第一步。










