
本文详解螺旋矩阵生成中因边界条件处理不当导致的 ArrayIndexOutOfBoundsException 问题,重点分析奇数阶矩阵失败的根本原因,并提供健壮、易理解的双指针循环解法及关键修正要点。
本文详解螺旋矩阵生成中因边界条件处理不当导致的 `arrayindexoutofboundsexception` 问题,重点分析奇数阶矩阵失败的根本原因,并提供健壮、易理解的双指针循环解法及关键修正要点。
在实现螺旋矩阵(Spiral Matrix)生成时,一个常见陷阱是:代码对偶数阶矩阵运行正常,但在奇数阶(如 n=3、5、7)时抛出 ArrayIndexOutOfBoundsException。这并非偶然,而是源于循环边界控制逻辑中的隐含缺陷——尤其在最后一圈仅剩单行或单列时,原有四重 for 循环未做“是否仍有有效区间”的前置校验。
回顾原始代码的问题核心:
// ❌ 错误示例(n=5 时在第3轮迭代中触发越界)
for(int i = leftCol; i < rightCol; i++) { ... } // → 当 leftCol == rightCol 时,该循环不执行(ok)
for(int j = topRow; j < bottomRow; j++) { ... } // → 当 topRow == bottomRow 时,该循环不执行(ok)
for(int i = rightCol; i > leftCol; i--) { ... } // → 当 rightCol == leftCol + 1 时,i 初始为 rightCol,执行一次后 i-- 变为 leftCol,循环结束(ok)
for(int j = bottomRow; j > topRow; j--) { ... } // → 同理,看似安全?但问题出现在 更新边界后进入下一轮 while 循环时:当 n=5,经过两轮填充后,状态变为:
-
topRow = 2,bottomRow = 2,leftCol = 2,rightCol = 2
此时num = 25(即n*n),而 while 条件是num (即 <code>num ),仍会进入第三轮!
第三轮中:
- 第一个 for 循环:
i从leftCol=2到rightCol=2(不满足i ),跳过 ✅ - 第二个 for 循环:
j从topRow=2到bottomRow=2(不满足j ),跳过 ✅ - 第三个 for 循环:
i从rightCol=2递减到leftCol=2(不满足i > leftCol),跳过 ✅ - 第四个 for 循环:
j从bottomRow=2递减到topRow=2(不满足j > topRow),跳过 ✅
✅ 所有循环均未执行,num 仍为 25,边界更新后变为:
-
topRow = 3,bottomRow = 1,leftCol = 3,rightCol = 1
⚠️ 此时 topRow > bottomRow 且 leftCol > rightCol —— 边界已交叉!
但 while 循环仍未终止(因 num=25 成立),下一轮将用非法边界再次尝试访问 <code>mat[3][...] 或 mat[...][3],直接越界!
✅ 正确解法:每次填充前,必须校验当前边界是否构成有效区间
以下是修复后的标准双指针螺旋填充实现(清晰、安全、符合常规思维):
public class SpiralMatrix {
public static void main(String[] args) {
generateSpiralMat(5); // ✅ 支持任意正整数 n
}
static void generateSpiralMat(int n) {
int[][] mat = new int[n][n];
int top = 0, bottom = n - 1;
int left = 0, right = n - 1;
int num = 1;
while (num <= n * n) {
// ➡️ 从左到右:top 行,[left, right]
if (top <= bottom) {
for (int i = left; i <= right; i++) {
mat[top][i] = num++;
}
top++;
}
// ⬇️ 从上到下:right 列,[top, bottom]
if (left <= right) {
for (int j = top; j <= bottom; j++) {
mat[j][right] = num++;
}
right--;
}
// ⬅️ 从右到左:bottom 行,[right, left](注意:<=)
if (top <= bottom) {
for (int i = right; i >= left; i--) {
mat[bottom][i] = num++;
}
bottom--;
}
// ⬆️ 从下到上:left 列,[bottom, top](注意:>=)
if (left <= right) {
for (int j = bottom; j >= top; j--) {
mat[j][left] = num++;
}
left++;
}
}
printMat(mat);
}
static void printMat(int[][] mat) {
for (int[] row : mat) {
for (int val : row) {
System.out.printf("%2d ", val);
}
System.out.println();
}
}
}? 关键修复点总结:
- 使用
替代 <code>(使单元素行/列也能被填充,如 <code>for (int i = left; i ); -
每个方向填充前增加区间有效性判断:
if (top 和 <code>if (left —— 这是防止奇数阶崩溃的<strong>最核心补丁</strong>; - 边界更新(
top++,right--,bottom--,left++)严格与对应方向配对,逻辑对称; - 循环条件保持
num ,语义更直观。
? 进阶提示:该模式可无缝扩展至「螺旋遍历」(Spiral Order Traversal)或「螺旋压缩」等变体,只需将赋值操作替换为读取/处理逻辑即可。
通过严谨的边界守卫和对退化区间的显式处理,即可彻底规避奇偶维度差异带来的运行时异常,写出真正鲁棒的螺旋矩阵生成代码。

















