昨天看见网上有两个贴子,关于矩阵数字的问题,仔细发现两个试题的算法很相似。
问题1
当参数是1就输出
1
当参数是2就输出
222
212
222
当参数是3就输出
33333
32223
32123
32223
33333
问题2
int i=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
int i=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
分析
仔细看看两个试题,算法其实很相似,如下图所示。
1. 可分解成一圈一圈的,每一圈的规律都相同,如红色圈与黄色圈、蓝色圈遵循相同的规律,如图G1和G2;
2. G1的每一圈用相同的数字填充,而G2的每一圈则依次递增,递增步长为1;
3. 先初始化最外圈,再缩小一圈,直到最后一圈(或最中心,第2题视奇数和偶数不同);如图G1-1, G1-2, G1-2和G2-1, G2-2, G2-2;
4. 每一圈初始化的时候,可分解为四个边,每个边的规律也是相同的,G1-1值不变,G2-1依次递增,步长为1;
5. 第一边初始化的时候,依照红、黄、蓝、绿的顺序依次,如图G1-1和G2-1;
6. 依照上述规律,可以通过递归方法简单实现;当然,这只是其中的一种方法,只是有趣而已;
代码如下:
public class ArrayTest {
/*
* n = 3
* 3 3 3 3 3
* 3 2 2 2 3
* 3 2 1 2 3
* 3 2 2 2 3
* 3 3 3 3 3
*/
public static int[][] getArray1(int n){
int[][] a = null;
int lenght = (n-1)*2+1;
if(n<=0){
return null;
}else if(n == 1){
a = new int[1][1];
a[0][0] = n;
show(a);
}
else{
a = new int[lenght][lenght];
/*
* initial the bytes's circumference with value n
*/
for( int i=0; i<lenght-1; i++){
a[0][i] = n; // red
a[i][lenght-1] = n; // yellow
a[lenght-1][lenght-1-i] = n; // blue
a[lenght-1-i][0] = n; // green
}
show(a);
/*
* copy inside bytes
*/
int[][] inside = getArray1(n-1);
if( null != inside){
for(int x=0; x<inside.length;x++){
for(int y=0; y<inside[x].length;y++){
a[x+1][y+1] = inside[x][y];
}
}
}
}
return a;
}
/*
* 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
*/
public static int[][] getArray2(int n, int start){
int[][] a = null;
int step = 0;
if(n<=0){
return null;
}else if( n==1 ){
a = new int[1][1];
a[0][0] = start;
show(a);
}else{
a = new int[n][n];
/*
* initial the bytes's circumference with start+step
* step 1: init red
* step 2: init yellow
* step 3: init blue
* step 4: init green
* Of course you can init within 1 for loop, but it less readable
*/
for( int i=0; i<n-1; i++){
a[0][i] = start + step++;
}
for( int i=0; i<n-1; i++){
a[i][n-1] = start + step++;
}
for( int i=0; i<n-1; i++){
a[n-1][n-1-i] = start + step++;
}
for( int i=0; i<n-1; i++){
a[n-1-i][0] = start + step++;
}
show(a);
/*
* copy inside bytes
*/
int[][] inside = getArray2(n-2, start+step);
if( null != inside){
for(int x=0; x<inside.length;x++){
for(int y=0; y<inside[x].length;y++){
a[x+1][y+1] = inside[x][y];
}
}
}
}
return a;
}
private static void show(int[][] a){
if(null == a) return;
int max = 0;
for(int i=0; i<a.length;i++){
for(int j=0; j<a[i].length;j++){
if(a[i][j]>max) max=a[i][j];
}
}
for(int i=0; i<a.length;i++){
for(int j=0; j<a[i].length;j++){
System.out.print(formatVale(a[i][j],String.valueOf(max).length()));
}
System.out.println();
}
}
private static String formatVale(int value, int length){
StringBuilder sb = new StringBuilder();
String idstr = String.valueOf(value);
int idlength = idstr.length();
for(int i=0; i<length-idlength;i++){
sb.append(' ');
}
sb.append(' ');
sb.append(idstr);
return sb.toString();
}
public static void main(String[] args) {
int[][] a1 = getArray1(3);
show(a1);
int[][] a2 = getArray2(5,1);
show(a2);
}
}