如何实现矩阵非角落元素的环形遍历(替代暴力写法)
嗨,这个问题问到点子上了!暴力写法在固定规模的矩阵里确实能凑合用,但矩阵一变大就完全没法维护,咱们得先把你这套遍历路径的规律提炼出来,改成通用的代码才行。
先拆解你现在的暴力代码里的规律:你针对9x9矩阵设计的3个环,每个环12个元素(4条边各3个),所有索引其实都可以用矩阵的边长N、中心位置mid、环的序号这几个变量来替代,不用写死数字。
第一步:提炼规律
以你用的9x9矩阵为例:
- N=9,中心位置
mid = N/2 = 4(整数除法) - 环的数量
numRings = (N-3)/2 = 3(刚好对应你写的3个环) - 每条边的元素数
sideLen = numRings = 3
你的4条遍历边的规律可以转换成:
- 第一条边:行固定为
(mid - numRings +1) - 环序号,列从mid+1往左数3个(从5到3) - 第二条边:列固定为
(mid - numRings +1) - 环序号,行从mid-1往下数3个(从3到5) - 第三条边:行固定为
(mid + numRings -1) + 环序号,列从mid-1往右数3个(从3到5) - 第四条边:列固定为
(mid + numRings -1) + 环序号,行从mid+1往上数3个(从5到3)
第二步:写出通用代码
把上面的规律转换成Java代码,就能适配任意奇数阶的矩阵(比如11x11、13x13):
public static int[][] customNonCornerRingTraversal(int[][] matrix) { int N = matrix.length; // 你的遍历路径适合奇数阶矩阵,先做校验 if (N % 2 == 0) { throw new IllegalArgumentException("This traversal path works for odd-sized square matrices only"); } int mid = N / 2; int numRings = (N - 3) / 2; int sideLength = numRings + 1; // 每条边的元素数,对应你例子里的3 int[][] rings = new int[numRings + 1][4 * sideLength]; for (int ringIdx = 0; ringIdx <= numRings; ringIdx++) { int currentPos = 0; // 第一条边:左上到右上的竖边(向上遍历) int row1 = (mid - numRings) - ringIdx; for (int col = mid + 1; col >= mid + 1 - (sideLength - 1); col--) { rings[ringIdx][currentPos++] = matrix[row1][col]; } // 第二条边:右上到右下的横边(向下遍历) int col2 = (mid - numRings) - ringIdx; for (int row = mid - 1; row <= mid - 1 + (sideLength - 1); row++) { rings[ringIdx][currentPos++] = matrix[row][col2]; } // 第三条边:右下到左下的竖边(向下遍历) int row3 = (mid + numRings) + ringIdx; for (int col = mid - 1; col <= mid - 1 + (sideLength - 1); col++) { rings[ringIdx][currentPos++] = matrix[row3][col]; } // 第四条边:左下到左上的横边(向上遍历) int col4 = (mid + numRings) + ringIdx; for (int row = mid + 1; row >= mid + 1 - (sideLength - 1); row--) { rings[ringIdx][currentPos++] = matrix[row][col4]; } } return rings; }
拓展:通用的不碰角落环形遍历
如果你不需要严格遵循当前的路径,只是想实现任意方阵(奇数/偶数阶)的不碰角落环形遍历(从外到内,顺时针/逆时针),可以用更通用的边界法:
- 对每个环,定义它的上下左右边界(
top、bottom、left、right) - 遍历四条边时,跳过四个角落的元素(比如上边从
left+1到right-1,而不是从left到right)
示例代码如下(顺时针遍历,从外到内):
import java.util.ArrayList; import java.util.List; public class GeneralRingTraversal { public static List<List<Integer>> generalNonCornerRings(int[][] matrix) { List<List<Integer>> rings = new ArrayList<>(); int N = matrix.length; if (N == 0 || matrix[0].length != N) { throw new IllegalArgumentException("Input must be a square matrix"); } int level = 0; while (level < N / 2) { int top = level; int bottom = N - 1 - level; int left = level; int right = N - 1 - level; // 单个元素或无有效元素,停止遍历 if (top == bottom || left == right) { break; } List<Integer> currentRing = new ArrayList<>(); // 上边:从左到右,跳过左右角落 for (int col = left + 1; col < right; col++) { currentRing.add(matrix[top][col]); } // 右边:从上到下,跳过上下角落 for (int row = top + 1; row < bottom; row++) { currentRing.add(matrix[row][right]); } // 下边:从右到左,跳过左右角落 for (int col = right - 1; col > left; col--) { currentRing.add(matrix[bottom][col]); } // 左边:从下到上,跳过上下角落 for (int row = bottom - 1; row > top; row--) { currentRing.add(matrix[row][left]); } rings.add(currentRing); level++; } return rings; } }
这样不管是9x9还是100x100的矩阵,都能自动处理所有不碰角落的环,不用手动写任何固定索引~
内容的提问来源于stack exchange,提问作者Raccoon
相关产品推荐
相关产品推荐

