题目:输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。例如,如果输入如下矩阵:
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。
这道题不涉及复杂的数据结构和算法,但会有多个循环,并且需要判断边界条件。
可以把矩阵看成若干个圈,循环打印矩阵,每次打印矩阵中的一个圈。
若矩阵的行数是row,列数是col。打印第一圈的左上角的坐标是(0,0),第二圈的左上角的坐标是(1,1),······,以此类推。我们发现,左上角的坐标中行标和列标总是相同的。
对于5*4的矩阵,最后一圈左上角的坐标是(1,1),我们发现5>1*2且4>1*2。
对于5*5的矩阵,最后一圈左上角的坐标是(2,2),我们发现5>2*2且5>2*2仍成立。
于是可以得出,让循环继续的条件是col>startCol*2并且row>startRow*2。
我们需要考虑如何打印矩阵的每一圈。
将打印一圈分为四步:
- 从左到右打印一行。
- 从上到下打印一列。
- 从右到左打印一行。
- 从下到上打印一列。
最后一圈可能只有一行、一列或一个数字。
打印时每一步的前提条件。
第一步总是需要的,打印一圈至少有一步。即便只有一行。
需要第二步的前提条件是终止行号大于起始行号。
需要第三步的前提条件是终止行号大于起始行号且终止列号大于起始列号。(圈内至少两行两列)
需要第四步的前提条件是终止行号比起始行号至少大2,同时终止列号大于起始列号。(圈内至少三行两列)
package offer;
public class Test02 {
public static void main(String[] args) {
int[][] num=new int[][] {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};
PrintMatrix(num,4,4);
}
public static void PrintMatrix(int[][] numbers,int col,int row) {
if(numbers==null||col<=0||row<=0)
return;
int start=0;
while(col>start*2&&row>start*2) {
PrintMatrixInCircle(numbers,col,row,start);
start++;
}
}
public static void PrintMatrixInCircle(int[][] numbers,int col,int row,int start) {
int endCol=col-1-start;
int endRow=row-1-start;
//从左到右打印一行
for(int i=start;i<=endCol;++i) {
int number=numbers[start][i];
System.out.print(number+"\t");
}
//从上到下打印一列
if(endRow>start) {
for(int i=start+1;i<=endRow;++i) {
int number=numbers[i][endCol];
System.out.print(number+"\t");
}
}
//从右到左打印一行
if(start<endCol&&start<endRow) {
for(int i=endCol-1;i>=start;--i) {
int number=numbers[endRow][i];
System.out.print(number+"\t");
}
}
//从下到上打印一列
if(start<endCol&&start<endRow-1) {
for(int i=endRow-1;i>=start+1;--i) {
int number=numbers[i][start];
System.out.print(number+"\t");
}
}
}
}