一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情
螺旋矩阵 II
给你一个正整数 n,生成一个包含 1 到 n^2 所有元素, 且元素按顺时针螺旋排列的 n x n 正方形矩阵 matrix
解题思路
模拟顺时针画矩阵的过程:
- 从左到右填充上行;
- 从上到下补充右列;
- 从右到左补充下列;
- 从下到上补充左列
由外向内画圈,一圈一圈地画下去。
这道题的难点在于每层循环的边界条件,对于这种多层循环条件,很容易写着写着,边界 就变了,导致程序难以正常执行。
所以在编写代码之前就要确定循环的边界条件,在这个大前提下,进行每个循环的逻辑编写。
数组遍历,下标与长度差值为1,所以确定所有边界:左闭右开
边界的确定在于
- n 与循环周期的关系 即循环条件 cycle? cycle = n / 2
- 考虑 offset的初始值取多少?offset = 1, 比如 n = 3, 第二例的最后一个值是不需要第一行遍历赋值的,而是由最后一列赋值;同理 最后一列最后一行同样不由最后一列赋值,而是由最后一行赋值,所以 offset = 1
- 找出 每层长度 与 索引 和 整数 n 以及 offset 的规律 length = n + starty/startx - offset
流程图
代码实现
public class Solution {
public int[][] generateMatrix(int n) {
int[][] nums = new int[n][n];
// 确定循环周期
int cycle = n/2;
// 设置起始下标
int startx = 0;
int starty = 0;
int i;
int j;
// 设置每个周期循环时控制每层遍历长度
// 因为是一个正方形顺时针填充,即上下左右,所以每层遍历
// 不需要遍历到最后一个值,因为上层最后一个值时右边第一个值的开始
// 右边最后一个值是下层最后一个值,而下层最开始的值是左边第一个值的开始
// 所以 offset 初始值设置为 1
int offset = 1;
// 正方形矩阵最小值为1
int count = 1;
// 开始周期循环画矩阵
while(cycle-- > 0){
i = startx;
j = starty;
// 上边从左到右
for(; j<n+starty-offset; j++){
nums[i][j] = count++;
}
// 左边从上到下
for(; i<n+startx-offset; i++){
nums[i][j] = count++;
}
// 下边从右到左
for(; j>starty; j--){
nums[i][j] = count++;
}
// 左边从下到上
for(; i>startx; i--){
nums[i][j] = count++;
}
// 每画完一层 startx starty 下标自增1
startx++;
starty++;
// 偏移量 +2 即画一层,每层长度遍历就要 -2
// 上下左右都有值,中间的长度可不就减 2 了
offset += 2;
}
// 确定中间值,如果 n 为奇数
if(n%2!= 0){
// 设置中间下标索引,当 n 为奇数时,
int mid = n/2;
nums[mid][mid] = n * n;
}
return nums;
}
}
复制代码