
本文详解如何在 java 中对二维数组每行内相邻的相同非零元素进行左向合并(如 2+2→4,右侧置0),并规避越界访问、重复合并等常见陷阱。
本文详解如何在 java 中对二维数组每行内相邻的相同非零元素进行左向合并(如 2+2→4,右侧置0),并规避越界访问、重复合并等常见陷阱。
在实现类似“2048”风格的数组滑动合并逻辑时,一个典型需求是:对二维数组每一行中从左到右连续出现的两个相等且非零元素,将其合并为两倍值,并置于左侧位置,右侧元素清零。例如 {0, 0, 2, 2} → {0, 0, 4, 0}。但直接套用双层循环容易引发运行时异常或逻辑错误,需特别注意边界与合并顺序。
✅ 正确实现要点
列循环上限必须为 arr[i].length - 1
原始代码中 col仅合并非零元素(可选但推荐)
题目示例中 0 不参与合并({0, 0, 2, 2} → {0, 0, 4, 0}),若不限制,0 == 0 会被误合并为 0,造成冗余操作甚至掩盖真实逻辑。建议添加 arr[i][j] != 0 判断。一次扫描、单次合并,避免连锁反应
本例要求“相邻即合并”,不递归处理(如 {2,2,2,2} 应变为 {4,0,4,0},而非 {8,0,0,0})。因此无需额外移位或多次遍历,标准单次左扫描即可。
? 完整可运行示例代码
import java.util.Arrays;
public class ArrayMerger {
public static void mergeAdjacentInRows(int[][] board) {
if (board == null) return;
for (int i = 0; i < board.length; i++) {
// 每行内从左到右扫描,比较当前元素与右侧元素
for (int j = 0; j < board[i].length - 1; j++) {
// 仅当两者相等且非零时合并(符合游戏逻辑直觉)
if (board[i][j] != 0 && board[i][j] == board[i][j + 1]) {
board[i][j] *= 2; // 左侧元素翻倍
board[i][j + 1] = 0; // 右侧元素清零
}
}
}
}
public static void main(String[] args) {
int[][] board = {
{0, 2, 4, 2},
{0, 0, 2, 2},
{2, 2, 0, 0},
{0, 5, 0, 2},
{2, 2, 2, 2}, // 验证多组相邻:→ {4,0,4,0}
{2, 2, 2, 0} // → {4,0,2,0}
};
mergeAdjacentInRows(board);
System.out.println(Arrays.deepToString(board));
// 输出:
// [[0, 2, 4, 2], [0, 0, 4, 0], [4, 0, 0, 0], [0, 5, 0, 2], [4, 0, 4, 0], [4, 0, 2, 0]]
}
}⚠️ 注意事项与进阶提示
- 不可逆性:该合并操作会直接修改原数组。如需保留原始数据,请先深拷贝(Arrays.stream(board).map(r -> r.clone()).toArray(int[][]::new))。
- 方向扩展:若需支持上/下/右合并,只需调整循环顺序与索引逻辑(例如向上合并:外层遍历列,内层遍历行 0 到 length-1)。
- 与“移动+合并”分离:真实游戏逻辑中,“合并”通常发生在“所有元素先向指定方向滑动靠拢”之后。本文仅解决“滑动后相邻元素的合并”子问题。
- 性能:时间复杂度为 O(m×n),空间复杂度 O(1),适用于常规棋盘规模(如 4×4、6×6)。
掌握这一基础合并模式,是构建完整滑动拼图类算法的关键一步。务必以边界安全为前提,再叠加业务规则(如忽略零值、防止重复触发),方能写出健壮可靠的数组操作逻辑。










