最近同事有了跳槽的想法,接到的面试也不少,今天回来说被问到了一个算法题,题目是什么样的呢?就是要求输入一个数字打印出一个矩阵,比如我们输入的是2,则打印出的矩阵如下:
1 4
2 3
输入的是3打印的矩阵如下:
1 8 7
2 9 6
3 4 5
输入的是4打印的矩阵如下:
1 12 11 10
2 13 16 9
3 14 15 8
4 5 6 7
就是这么一道题,让设计程序,当时同事说完了以后自己就研究了起来,开始找规律,找了半天感觉除了第一列与最后一行有点规律外,其他的也没什么规律啊,一会向下一会向上的,还找到了第二行第二列的那个数等于(2n-1)+[2(n-1)-1]以外再也找不到什么规律了。后来只能换了其他思路,个人感觉唯一的规律就是一个逆时针循环添加矩阵的规律,想蜗牛壳一样越来越小,指到中心位置显示最大值。本人就索性给他叫蜗牛矩阵吧。找到了规律,那么怎么实现他呢。这个是重点。本人在这里说一下笨方法,就是用一个二维数组去保存每一个位置上的数字,先填充每一个位置上对应的数字,然后在循环打印这个二维数组,就好了,那么,问题又来了,就是如何填充这个二维数组呢,这是重点,先大致说一下思路:首先定义一个保存当前操作方向的类,主要的方向有四种,就是向上、向下、向左、向右,我们可以用枚举类来实现。然后,定义两个变量分别表示当前操作的数据在矩阵中所处的行row跟列 column,最后定义四个表示边界的变量,表示上边界的UpA,下边界的DownA,左边界的LeftA,右边界的RightA;当我们向下设置数据时行row改变,但是不能超过我们的下边界DownA,当我们到了最后一行时,因为是逆时针,所以我们需要向右设置数据,则需要将状态改为向右,列column加1,同时左边界LeftA也要加1,这样就完成了一次由上到下在到有边转变的过程。当上边界UpA等于下边界DownA并且左边界LeftA等于右边界RightA时表示数据填充完毕,然后我们就可以顺序打印这个矩阵了,记得加上换行打印,可能说的不是很清楚,还是看代码比较直观。
下边看一下具体实现:
public class Test {
public static void main(String[] args) {
//相当于输入值;
int i = 8;
//当前位置上的值
int k = 1;
//保存数据的数组
int data[][] = new int[i][i];
//定义当前状态
Type type = Type.down;
//当前行
int row = 0;
//当前列;
int c = 0;
//上下左右边界值;
int upA = 0;
int leftA = 0;
int downA = i - 1;
int rightA = i - 1;
while (true) {
data[row][c] = k++;
if (upA == downA && leftA == rightA) {
break;
}
switch (type) {
case down:
//当前行小于下边界;
if (row < downA) {
//行数加1,表示移动到下一行;
row += 1;
} else {
//到达最后一行,需要向右操作数据了,列数+1,状态变为向右,左边界+1;
c += 1;
type = Type.right;
leftA += 1;
}
break;
case right:
if (c < rightA) {
c += 1;
} else {
row -= 1;
type = Type.up;
downA -= 1;
}
break;
case up:
if (upA < row) {
row -= 1;
} else {
c -= 1;
type = Type.left;
rightA -= 1;
}
break;
case left:
if (leftA < c) {
c -= 1;
} else {
row += 1;
type = Type.down;
upA += 1;
}
break;
}
}
for (int a = 0; a < i; a++) {
for (int b = 0; b < i; b++) {
System.out.print(data[a][b] + " ");
}
System.out.println("");
}
}
public enum Type {
down, right, up, left
}
}
这样便实现了同事所说的功能,如果您
有好的实现方式希望留言,谢谢!