闲暇之余研究了螺旋方阵的生成方式,包括顺时针螺旋(clockwise)、逆时针螺旋(anticlockwise),算法从最外层的左上角(top left)开始构造整个Spiral Matrix。
代码实现如下:
public class Test{
public static final String LINE_SEP = "-----------------";
public static void main(String[] args){
SpiralMatrix sm = new SpiralMatrix(3);
sm.print(true, true);
System.out.println(LINE_SEP);
sm.print(true, false);
System.out.println(LINE_SEP);
sm.print(false, true);
System.out.println(LINE_SEP);
sm.print(false, false);
}
}
class SpiralMatrix{
private int size;
SpiralMatrix(){
size = 3;
}
SpiralMatrix(int size){
this.size = size;
}
public void print(boolean clockwise, boolean ascending){
int x = 0;
int y = 0;
int n = size;
int increX = 0;
int increY = 0;
int[][] arr = new int[size][size];
int value = 1;
int increment = 1;
if(!ascending){
value = size*size;
increment = -1;
}
while(n > 0){
//the center point
if(n == 1){
arr[x][y] = value;
break;
}
if(clockwise){//top left -> right
increX = 0;
increY = 1;
}else{
increX = 1;
increY = 0;
}
for(int i=0; i<n-1; i++){
arr[x][y] = value;
value += increment;
x += increX;
y += increY;
}
if(clockwise){//top right -> down
increX = 1;
increY = 0;
}else{
increX = 0;
increY = 1;
}
for(int i=0; i<n-1; i++){
arr[x][y] = value;
value += increment;
x += increX;
y += increY;
}
if(clockwise){//bottom right -> left
increX = 0;
increY = -1;
}else{
increX = -1;
increY = 0;
}
for(int i=0; i<n-1; i++){
arr[x][y] = value;
value += increment;
x += increX;
y += increY;
}
if(clockwise){//bottom left -> up
increX = -1;
increY = 0;
}else{
increX = 0;
increY = -1;
}
for(int i=0; i<n-1; i++){
arr[x][y] = value;
value += increment;
x += increX;
y += increY;
}
//to the inner round
n -= 2;
x++;
y++;
}
for(x=0; x<size; x++){
for(y=0; y<size; y++){
System.out.printf("%4d", arr[x][y]);
}
System.out.println();
}
}
}
输出结果:
1 2 3
8 9 4
7 6 5
-----------------
9 8 7
2 1 6
3 4 5
-----------------
1 8 7
2 9 6
3 4 5
-----------------
9 2 3
8 1 4
7 6 5
上述代码考虑了旋转的方向和是递增还是递减,太过繁琐,最近刚好刷到力扣螺旋矩阵的两道题目:
给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序(从左上角开始),返回矩阵中的所有元素。
// 轮换坐标(x,y),记录长和宽的写法
public List<Integer> spiralOrder(int[][] matrix) {
// 由外圈到内圈逐个打印
List<Integer> ans = new ArrayList<>();
if(matrix.length==0)return ans;
int numX = matrix[0].length-1;
int numY = matrix.length-1;
int x=0,y=0;
while(numX>=0 && numY>=0) {
if(numX==0) {
for (int i = 0; i <= numY; i++) {
ans.add(matrix[x++][y]);
}
break;
} else if(numY==0) {
for (int i = 0; i <= numX; i++) {
ans.add(matrix[x][y++]);
}
break;
} else {
for (int i = 0; i < numX; i++) {
ans.add(matrix[x][y++]);
}
for (int i = 0; i < numY; i++) {
ans.add(matrix[x++][y]);
}
for (int i = 0; i < numX; i++) {
ans.add(matrix[x][y--]);
}
for (int i = 0; i < numY; i++) {
ans.add(matrix[x--][y]);
}
x++;
y++;
numX-=2;
numY-=2;
}
}
return ans;
}
给定一个正整数 n,生成一个包含 1 到 n^2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。
public int[][] generateMatrix(int n) {
int[][] ans = new int[n][n];
int x = 0, y = 0;
int len = n - 1;
int num = 1;
while (len >= 0) {
if (len > 0) {
// 填充一圈数字
for (int i = 0; i < len; i++) {
ans[x][y++] = num++;
}
for (int i = 0; i < len; i++) {
ans[x++][y] = num++;
}
for (int i = 0; i < len; i++) {
ans[x][y--] = num++;
}
for (int i = 0; i < len; i++) {
ans[x--][y] = num++;
}
// 跳到更内一层的起点
x++;
y++;
} else {
// 只剩最后一个数了
ans[x][y] = num;
}
len -= 2;
}
return ans;
}