矩阵各元素相邻(含对角线)元素求和的优雅实现方式
问题:矩阵相邻元素求和的优雅实现方案
需要对n×m整数矩阵中的每个元素,计算其所有相邻元素(含对角线相邻)的和。按索引遍历时,边界及角落元素(如[0][n-1])会因部分相邻元素不存在引发索引越界(例如该位置的[-1][n-2]、[-1][n-1]等元素不存在)。
我想到的简单方案要么是通过大量分支判断处理不同情况:
if(i != 0){ //check all fields }else if(i == 0 && j == 0){ //check only fields left, below and left-below }else if(...) ... }
要么是对每个相邻元素的访问使用try-catch捕获异常:
int count = 0; try{ count += matrix[i-1][j]; }catch(IndexOutOfBoundsException e){ .... }
但这两种方法都不够优雅,请问是否有更优的解决方案?
更优解决方案
方法一:遍历偏移量+统一边界检查
定义所有相邻位置的8个方向偏移量集合:[(-1,-1), (-1,0), (-1,1), (0,-1), (0,1), (1,-1), (1,0), (1,1)]。对每个元素(i,j),遍历这8个偏移量得到相邻坐标(x=i+dx, y=j+dy),然后统一检查x是否在[0, n-1]、y是否在[0, m-1]范围内,符合条件则累加对应元素值。
这种方式无需大量分支判断,逻辑统一清晰,代码示例:
// 定义8个方向的偏移量 int[][] dirs = {{-1,-1}, {-1,0}, {-1,1}, {0,-1}, {0,1}, {1,-1}, {1,0}, {1,1}}; int n = matrix.length; int m = matrix[0].length; int[][] result = new int[n][m]; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { int sum = 0; for (int[] dir : dirs) { int x = i + dir[0]; int y = j + dir[1]; // 统一检查坐标合法性 if (x >= 0 && x < n && y >= 0 && y < m) { sum += matrix[x][y]; } } result[i][j] = sum; } }
方法二:给矩阵补零边界
在原矩阵四周添加一层值为0的元素,让原矩阵所有元素都处于新矩阵的内部位置,这样访问相邻元素时不会触发索引越界,计算完成后再剔除补的边界即可。
这种方式完全不需要边界检查,代码更简洁,适合矩阵规模不大的场景:
int n = matrix.length; int m = matrix[0].length; // 构造补零后的矩阵,尺寸为(n+2)×(m+2) int[][] paddedMatrix = new int[n+2][m+2]; // 将原矩阵内容填充到补零矩阵的中间区域 for (int i = 0; i < n; i++) { System.arraycopy(matrix[i], 0, paddedMatrix[i+1], 1, m); } int[][] result = new int[n][m]; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { // 原矩阵(i,j)对应补零矩阵的(i+1,j+1),直接累加8个相邻元素 int sum = paddedMatrix[i][j] + paddedMatrix[i][j+1] + paddedMatrix[i][j+2] + paddedMatrix[i+1][j] + paddedMatrix[i+1][j+2] + paddedMatrix[i+2][j] + paddedMatrix[i+2][j+1] + paddedMatrix[i+2][j+2]; result[i][j] = sum; } }
内容的提问来源于stack exchange,提问作者RandomNobody
相关产品推荐
相关产品推荐

