思路:把所有的数字还有*当成一个彩带,绕圈缠绕在一个框内
外层大循环条件是彩带长度
大循环内部嵌套四个小循环分别处理:上边——>右边——>下边——>左边(顺时针缠绕)
关键:处理四个角点的时候,因为是两边交汇处,如果上个边已经处理了,那下个边就要跳过该坑位;
package com.huawei;
import java.util.Arrays;
public class 螺旋矩阵变形 {
public static void main(String[] args) {
int n = 9;
int hang = 4;
int lie = n % hang != 0 ? n / hang + 1 : n / hang; //确定列数
String ret[][] = new String[hang][lie];
int sum = hang * lie; //确定需要填入的个数(包括数字和*)
int i = 1,h=0,l=0,count=0;
/**
* while里面是一个循环,一个循环下来会把最外圈的全部填完,每次循环的开始都是ret[h][l]
* 当一次小循环结束之后就h++ l++ 第一次是从ret[0][0]开始
* 第二次是从ret[1][1]开始
*每个大循环里面又有四个小循环,负责填充四个边
*/
while (i <= sum) {
while (l < lie-count) { //lie是列数,每循环一次lie数就会-1,count是记录循环次数的,在本次循环结束时候会+1
if (ret[h][l] ==null) { //填写上边,有一个问题是,在两条边的交点的角,两个小循环都会扫描到,此时需要用ret[][]==null来判断是否已经被上一个处理过了
if(i<=n) //填数字
ret[h][l] = String.valueOf(i);
else //填字符
ret[h][l] = "*";
i++;
}
l++; //由于本次小循环是为了填上边,所以每次填完之后,列值都会+1
}
l--; //由于跳出循环的时候l=lie-count,已经超出了界限(因为填完最后一个的时候,l又++了)
//此后的三个小循环都是给ret[l][h]赋值,代码高度相似,只需要判断h和l的变化就行了
while (h < hang-count) {
if (ret[h][l] ==null) {
if(i<=n)
ret[h][l] = String.valueOf(i);
else
ret[h][l] = "*";
i++;
}
h++;
}
h--;
while (l >= count) {
if (ret[h][l] ==null) {
if(i<=n)
ret[h][l] = String.valueOf(i);
else
ret[h][l] = "*";
i++;
}
l--;
}
l++;
while (h >= count) {
if (ret[h][l] == null) {
if(i<=n)
ret[h][l] = String.valueOf(i);
else
ret[h][l] = "*";
i++;
}
h--;
}
h++;//左边填充到了最上面,现在h=0,l=0
h++; //这两个h,l的修改就是为了让下次while循环的开头是ret[1][1]
l++;
count++;
}
for (int j = 0; j < hang; j++) {
System.out.println(Arrays.toString(ret[j]));
}
}
}