题目速览
小U面临一个有趣的任务:在一个nxn的方阵中填入1到nxn这些数字,并要求按照蛇形顺序从右上角开始,沿着方阵的边界顺时针进行填充。
蛇形填充的特殊排列方式使得每一层数字呈现出波浪形的排列方式。 具体示例:
1 2 3 4
12 13 14 5
11 16 15 6
10 9 8 7
思路讲解
- 首先我们定义最左边和最右边的边界为left和right,定义最上边和最下边的边界为top和bottom
- 对于每层,从左上方开始以顺时针的顺序遍历所有元素。假设当前层的左上角位于(top,left),右下角位于(bottom,right),按照如下顺序遍历当前的元素
- 从左到右遍历上侧元素,依次为(top,left)到(top,right)
- 从上到下遍历右侧元素,依次为(top,right)到(top,bottom)
- 如果left < right 且top < bottom,按照如下顺序遍历当前的元素
- 从右到左遍历下侧元素,依次为(bottom,right-1)到(bottom,left+1),
- 从下到上遍历左侧元素,依次为(bottom,left)到(top+1, left)
- 遍历完当前层的元素之后,将left和top分别增加 ,将right和bottom分别减少 ,进入下一层继续遍历,直到遍历完所有元素为止
算法流程
- 空值处理: 当n为空时,直接返回空列表 [] 即可。
- 初始化: 矩阵 左、右、上、下四个边界left,right,top,bottom用于打印的结果列表 res 。
- 循环打印: “从左向右、从上向下、从右向左、从下向上” 四个方向循环打印。
- 根据边界打印,即将元素按顺序添加至列表 res 尾部。
- 边界向内收缩 1 (代表已被打印)。
- 判断边界是否相遇(是否打印完毕),若打印完毕则跳出。
| 打印方向 | 1. 根据边界打印 | 2. 边界向内收缩 | 3. 是否打印完毕 |
|---|---|---|---|
| 从左向右 | 左边界l ,右边界 r | 上边界 t 加 1 | 是否 t > b |
| 从上向下 | 上边界 t ,下边界b | 右边界 r 减 1 | 是否 l > r |
| 从右向左 | 右边界 r ,左边界l | 下边界 b 减 1 | 是否 t > b |
| 从下向上 | 下边界 b ,上边界t | 左边界 l 加 1 | 是否 l > r |
代码实现
public static int[][] solution(int n) {
int[][] ans = new int[n][n];
int direct = 1;
int left = 0;
int right = n-1;
int up = 0;
int down = n-1;
int num = 1;
while(num <= n*n) {
if(direct == 1) {
for (int i = up; i <= down; i++) {
ans[i][right] = num;
num++;
}
right--;
direct = 2;
}
else if(direct == 2) {
for (int i = right; i >= left; i--) {
ans[down][i] = num;
num++;
}
down--;
direct = 3;
}
else if(direct == 3) {
for (int i = down; i >= up; i--) {
ans[i][left] = num;
num++;
}
left++;
direct = 4;
}
else {
for (int i = left; i <= right; i++) {
ans[up][i] = num;
num++;
}
up++;
direct = 1;
}
}
return ans;
}
补充思路:模拟
可以模拟螺旋矩阵的路径。初始位置是矩阵的左上角,初始方向是向右,当路径超出界限或者进入之前访问过的位置时,顺时针旋转,进入下一个方向。\
判断路径是否进入之前访问过的位置需要使用一个与输入矩阵大小相同的辅助矩阵,其中的每个元素表示该位置是否被访问过。当一个元素被访问时,将辅助矩阵中的对应位置的元素设为已访问。\
如何判断路径是否结束?由于矩阵中的每个元素都被访问一次,因此路径的长度即为矩阵中的元素数量,当路径的长度达到矩阵中的元素数量时即为完整路径,将该路径返回。
读者可自行思考解题方案