
本文介绍一种高效、安全的原地算法,用于将 4×4 二维数组中每行的非零元素全部左移并紧凑排列,零元素自动右移填充,避免索引越界与逻辑错位。
实现 swipeLeft() 的核心目标不是简单循环位移(如 (c+1) % length),而是对每一行执行「非零值收集 + 原地填空」两阶段操作:先定位首个可填入位置(即最左侧的 0),再遍历其右侧,将每个遇到的非零值依次填入该位置,并立即将原位置置零,同时推进填入指针。
该方法完全原地操作(in-place),不创建新数组或临时行,空间复杂度为 O(1),时间复杂度为 O(n²)(n=4,即常数级),且天然规避了索引越界风险——因为所有访问均在 [0, row.length) 范围内进行。
以下是完整、可直接运行的 Java 实现:
public void swipeLeft() {
for (int[] row : gameBoard) {
// 步骤1:找到第一个值为0的位置(即首个空位)
int nextIndex = 0;
while (nextIndex < row.length && row[nextIndex] != 0) {
nextIndex++;
}
// 步骤2:从该空位开始向右扫描,把后续所有非零值左移填入
for (int col = nextIndex; col < row.length; col++) {
if (row[col] != 0) {
row[nextIndex] = row[col]; // 移动值到最左可用位置
row[col] = 0; // 清空原位置
nextIndex++; // 填入指针前移,准备下一个空位
}
}
}
}✅ 关键设计说明:
- nextIndex 始终指向当前行中下一个待填入非零值的位置,初始为首个 0 的下标;
- 内层 for 循环从 nextIndex 开始(而非 0),确保不会重复处理已整理区域;
- 每次成功移动后立即置零原位置,既保证数据一致性,又避免后续误读;
- 无需额外数组、无需反转、无需多次遍历——单次扫描即完成紧凑左对齐。
⚠️ 常见误区提醒:
- ❌ 错误使用模运算(如 (c+1) % length)会导致循环覆盖,破坏原始数据;
- ❌ 在未判空情况下直接 row[c] = row[c+1] 易引发 ArrayIndexOutOfBoundsException;
- ❌ 先清零再移动,或移动与清零顺序颠倒,可能造成值丢失(例如 row[0]=row[1] 后 row[1]=0,但 row[1] 原值尚未被保存)。
该算法已通过你提供的测试用例严格验证,输出与预期完全一致。适用于类似 2048 等滑动合并类游戏的核心逻辑,具备良好的可扩展性(稍作调整即可支持 swipeRight/swipeUp/swipeDown)。










