面试时出现这样的题目,输入一个正整数n,实现螺旋矩阵。
比如输入5,输出
1 2 3 4 5
16 17 18 19 6
15 24 25 20 7
14 23 22 21 8
13 12 11 10 9
输入6,输出
1 2 3 4 5 6
20 21 22 23 24 7
19 32 33 34 25 8
18 31 36 35 26 9
17 30 29 28 27 10
16 15 14 13 12 11
当时哥睡眠不足,使用递归算法输出,发现无法实现。
后建立数学模型,得到完美的数学公式。
package test;
public class Test {
public static void main(String[] args) {
printMatrix(6);
}
public static int min(int i,int j)
{
return i<=j?i:j;
}
//i,j代表坐标,并且i,j都是从1开始计数
//k代表点(i,j)所在的圈数,圈数也是从1开始计数
public static void printMatrix(int n)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
int k=min(min(min(i,j),min(n+1-i,j)),min(i,n+1-j));
int sum=0;
if(k>1)
{
for(int v=1;v<k;v++)
sum=sum+4*(n+1-2*v);
}
if (i==k&&j>=k&&j<=n+1-k)
System.out.print(String.format("%5d",sum+j-k+1));
else if(j==n+1-k&&i>k&&i<=n+1-k)
System.out.print(String.format("%5d",sum+n+1-2*k+i-k+1));
else if(i==n+1-k&&j>=k&&j<n+1-k)
System.out.print(String.format("%5d",sum+2*(n+1-2*k)+n+2-k-j));
else if(j==k&&i>k&&i<n+1-k)
System.out.print(String.format("%5d",sum+3*(n+1-2*k)+n+2-k-i));
}
System.out.println();
}
}
}
思路是先确定元素(i,j)所在的圈数,比如如果n=5,(1,3)在第一圈,(1,5)在第一圈,(2,3)在第二圈,由int k=min(min(min(i,j),min(n+1-i,j)),min(i,n+1-j));
确定。第二步确定k圈前k-1圈的和,最后判断(i,j)在k圈的哪一边,进行相应的步数相加。
虽然算法复杂度在o(n^2),但是算法比较明了,当然也可以用构造法来做。
输入10,得到下面结果:
1 2 3 4 5 6 7 8 9 10
36 37 38 39 40 41 42 43 44 11
35 64 65 66 67 68 69 70 45 12
34 63 84 85 86 87 88 71 46 13
33 62 83 96 97 98 89 72 47 14
32 61 82 95 100 99 90 73 48 15
31 60 81 94 93 92 91 74 49 16
30 59 80 79 78 77 76 75 50 17
29 58 57 56 55 54 53 52 51 18
28 27 26 25 24 23 22 21 20 19