一、问题描述
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
输入输出
输入
[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]]
输出
[1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10]
二、思路
简而言之就是判断当前的数值打印之后下一步的前进方向。
从图中可以看出在矩阵顺时针打印过程中,前进方向是:右 \rightarrow 下 \rightarrow 左 \rightarrow 上。所以,在处理矩阵打印顺序时可以根据方向打印,当当前方向没有可打印数据时转变方向。
三、难点
1、关于标记方向的问题
在最开始我分别判断奇数和偶数矩阵,根据下标判断当前坐标的前进方向。但是我们发现,这样判断,每个坐标都有两个前进方向:(上下,左右),这就会导致在判断的时候代码逻辑复杂,bug很多。
后来,我摒弃了奇数偶数矩阵下标判断前进方向的方案,采用了direction标记前进方向。因为在打印过程只要选定一个方向,那么直到当前行(列)的数据打印完毕才会转向,这样一来,代码逻辑变得简单清晰。
2、关于是否转向的判定问题
采用direction标记方向以后,还面临一个问题,就是方向的转变。
在最开始,我采用的是if判断,如果当前方向还有未打印的数据,那么前进,否则转向。这样的情况下,会有四个判断转向的if语句,增加了代码运行时间,占用系统内存。
后来,思考之后发现,只需要判断每个方向的前进,当不需要前进的时候就要改变方向。只要一条语句就实现了打印转向。
3、出现运行超时
这个是由于逻辑代码连续多个(我用到了8个)判断语句造成的,也就是上面问题2里面提到的转向判断语句,后来将转向问题合并,代码就没有出现运行超时。
四、附上方向判断以及前进的逻辑处理代码
public static int[] getI_J(int[][] backUpMatrix, int m,int n, int i, int j, int direction) {
//backUpMatrix输入数组的标记,用来标记数字是否打印:-1已经打印,0未打印
//m输入数组维度,n输入数组子数组维度
//(i,j)当前数据的下标
//direction表示前进方向:0右1下2左3上
if (direction == 0 && (j + 1) < n && backUpMatrix[i][j + 1] != -1) {//right并且数组没有越界,并且下一个数字没有打印过
j++;
} else if (direction == 1 && (i + 1) < m && backUpMatrix[i + 1][j] != -1) {//down并且数组没有越界,并且下一个数字没有打印过
i++;
}else if (direction == 2 && (j - 1) > -1 && backUpMatrix[i][j - 1] != -1) {//down并且数组没有越界,并且下一个数字没有打印过
j--;
}else if (direction == 3 && (i - 1) > -1 && backUpMatrix[i - 1][j] != -1) {//down并且数组没有越界,并且下一个数字没有打印过
i--;
} else {
if(direction == 3){
direction = 0;
}else {
direction++;
}
}
return new int[]{i, j, direction};//返回下一个数据的坐标,以及下一个数据的前进方向
}
本文版权归本人所有,转载请联系本人